如何限制使用`malloc()`获取的内存而不限制堆栈?
我试图阻止学生代码在分配时狂奔,并拖延我的测试机器。 我试过了
setrlimit(RLIMIT_DATA, r);
其中r
是一个持有限制的结构。 但不幸的是,虽然这个限制阻止了brk
和sbrk
的分配,但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
的定义。