地址空间布局随机化(ALSR)和mmap

时间:2012-02-28 15:56:32

标签: c linux gcc x86-64 aslr

我希望由于地址空间布局随机化(ALSR),从另一个进程分叉的进程在调用mmap时会返回不同的地址。但正如我发现的那样,事实并非如此。为此目的,我做了以下测试程序。 malloc返回的所有地址对于父级和子级完全相同。 请注意, cl1 cl2 pl1 pl2 malloc内部使用{{1}因为它们是大块。

所以,我的问题是,为什么mmap即使在ALSR存在的情况下也不会返回不同的地址。也许是因为这里的随机种子对于原始和分叉过程是相同的。或者还有其他原因吗?

mmap

2 个答案:

答案 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也不为零。)