我希望由于地址空间布局随机化(ALSR),从另一个进程分叉的进程在调用mmap
时会返回不同的地址。但正如我发现的那样,事实并非如此。为此目的,我做了以下测试程序。 malloc
返回的所有地址对于父级和子级完全相同。
请注意, cl1 , cl2 , pl1 , pl2 的malloc
内部使用{{1}因为它们是大块。
所以,我的问题是,为什么mmap
即使在ALSR存在的情况下也不会返回不同的地址。也许是因为这里的随机种子对于原始和分叉过程是相同的。或者还有其他原因吗?
mmap
答案 0 :(得分:5)
ASLR主要随机化从用户空间地址空间顶部到堆栈的距离,以及从堆栈保留空间底部到第一个mmap
的距离(这可能是动态映射)连接器)。任何进一步的随机化都会对虚拟内存空间产生严重的碎片效应,因此会破坏需要进行大mmap
s的程序(例如,在32位计算机上进行1-2 GB的映射)。
我已经看到一些Linux发行版发布了修补内核,这些内核对mmap
返回的地址执行更多随机化。它们中的一些甚至会给你映射重叠与为堆栈保留的空间扩展,然后当堆栈增长时,它会破坏你的映射(导致一个巨大的安全漏洞,比任何非随机地址分配都要大得多) 。远离这些黑客。
答案 1 :(得分:4)
你不能重新随机化孩子的地址空间 - 所有指针都必须被修改,这在技术上是不可能的(运行时环境甚至不知道你的数据的哪一部分是指针)。
因此,您所看到的结果是预期的,来自fork的子节点在分叉时具有其父地址空间的精确副本,包括其虚拟地址布局。
您需要exec*
调用才能获得新的地址空间布局。
$ cat t.c
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
printf("%p\n", malloc((long)512e3));
if ((argc > 1) && fork()) {
execl("./a.out", "./a.out", NULL);
}
return 0;
}
$ gcc -Wall t.c
$ ./a.out 1
0x7f5bf6962010
0x7f3483044010
$ ./a.out 1
0x7f1ce7462010
0x7feb2adc2010
(并确保/proc/sys/kernel/randomize_va_space
也不为零。)