如何限制使用`malloc()`获取的内存而不限制堆栈?

我试图阻止学生代码在分配时狂奔,并拖延我的测试机器。 我试过了

setrlimit(RLIMIT_DATA, r); 

其中r是一个持有限制的结构。 但不幸的是,虽然这个限制阻止了brksbrk的分配,但C库只是故障转移到mmap并保持正确的分配。

我也试过了

 setrlimit(RLIMIT_AS, r) 

并且这会使进程停止,但是这种补救措施太严重了 – 进程无法从ENOMEM错误中恢复,因为代码在遇到malloc()返回的NULL值时所进行的调用没有堆栈空间。

我对二进制文件的控制有限,所以如果可以使用系统调用,我宁愿这样做。 但我需要一些方法来限制分配,而不会破坏流程的恢复能力。 有没有人有建议?

更新 :我找到了一个名为failmalloc的东西,但它并不是很复杂,虽然我可以使用它导致失败,但我总是得到gdb无法诊断的段错误。

进一步更新 :我发现setrlimit(RLIMIT_AS, r) 确实似乎完成了我想要的工作,至少在某些情况下 – 之后发生的段错误是由不相关模块中的错误引起的。 除非有人想出一些有趣的东西(或保留问题的理由),否则我可能会删除这个问题。

基于failmalloc使用的思想 ,您可以使用LD_PRELOAD *环境变量和函数插入来构建围绕malloc()的包装并在那里施加任何限制。

您需要使用dlsym()动态加载指向原始malloc()的指针。 您无法直接从包装器调用原始malloc() ,因为它将被解释为对包装器本身的递归调用。

 #define _GNU_SOURCE #include  #include  #include  void * malloc(size_t size) { static void * (*func)(size_t) = NULL; void * ret; if (!func) { /* get reference to original (libc provided) malloc */ func = (void *(*)(size_t)) dlsym(RTLD_NEXT, "malloc"); } /* impose any necessary restrictions before calling malloc */ ... /* call original malloc */ ret = func(size); /* impose any necessary restrictions after calling malloc */ ... return ret; } 

*请注意, LD_PRELOAD必须指定插入程序库的完整路径,并且为setuid程序禁用该库插入以防止出现安全问题。


使用dlsym()的另一种方法是使用GNU链接器--wrap symbol选项。

你可以强迫毫无戒心的学生使用宏吗? 🙂

 #define malloc(bytes) limited_malloc(bytes) 

以及限制可以做什么的limited_malloc的定义。