【发布时间】:2019-08-17 11:10:34
【问题描述】:
我在很多地方(musl 邮件列表、macOS 论坛等)都听说brk() 和sbrk() 不安全。其中很多地方要么根本不解释,要么解释的很模糊。例如,this 链接声明“这些功能从根本上被破坏了”,并继续说 malloc 和 sbrk 子系统完全被破坏了,它们破坏了堆,等等。
我的问题是:为什么会这样?如果malloc 的使用方式是它分配的内存块sbrk 大到足以平息或大大减少对进一步分配的需求,那么sbrk 和brk 不应该完全安全使用?
这是我对sbrk 和brk 的实现:
sbrk:
#include <unistd.h>
#include <stddef.h>
void *sbrk(intptr_t inc)
{
intptr_t curbrk = syscall(SYS_brk, NULL);
if( inc == 0 ) goto ret;
if( curbrk < 0 ) return (void *)-1;
curbrk((void *)(curbrk+inc));
ret:
return (void *)curbrk;
}
brk:
#include <unistd.h>
intptr_t brk(void *ptr)
{
if( (void *)syscall(SYS_brk, ptr) != ptr )
return -1;
else
return 0;
}
【问题讨论】:
-
文本
For an application to use them correctly, it must depend on the malloc subsystem never being used, but this is impossible to guarantee since malloc may be used internally by libc functions without documenting this to the application.中有解释。如果你的应用调用了 sbrk,而你的应用调用了 malloc,而 malloc 调用了 sbrk,而 sbrk 函数使用了全局上下文,那么结果将是一团糟。他们想消除 sbrk 功能,让用户不使用它,而不是因为它本身就是一个糟糕的设计。 -
“全局上下文”是什么意思?快速的 Google 搜索不会显示任何内容。
-
我的猜测是某些
malloc实现被编写为假设没有其他人在背后调用sbrk。例如,假设您调用p = malloc(N),其中 N 是一个很大的数字(可能是页面大小的倍数)。 malloc 执行sbrk(N)从操作系统获取内存并将此指针返回给您。稍后(没有任何对 malloc 的干预调用)你会做free(p)。现在 malloc “知道”它可以通过sbrk(-N)将内存返回给操作系统。如果你在两者之间调用了sbrk,那么你就有问题了。 -
awkwardly written, but good basic malloc introduction 使用
brk/sbrk编写您自己的内存管理器(仅限介绍级别)