5

我希望由于地址空间布局随机化(ALSR),从另一个进程派生的进程在调用mmap. 但我发现,事实并非如此。为此,我制作了以下测试程序。返回的所有地址malloc对于父母和孩子来说都是完全相同的。请注意mallocfor cl1 , cl2 , pl1 , pl2内部使用mmap,因为它们是大块。

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

int main()
{
  pid = fork();

  if (pid == 0)                // child
  {
    void * c1 = malloc( 4096 );
    void * c2 = malloc( 4096 );

    void * cl1 = malloc( (long)512e3 ); // internally uses mmap
    void * cl2 = malloc( (long)512e3 ); // internally uses mmap

    printf( "c1 = %p, c2 = %p, cl1 = %p, cl2 = %p!\n", c1, c2, cl1, cl2 );
  }
  else
  {
    void * p1 = malloc( 4096 );
    void * p2 = malloc( 4096 );

    void * pl1 = malloc( (long)512e3 ); // internally uses mmap
    void * pl2 = malloc( (long)512e3 ); // internally uses mmap

    printf( "p1 = %p, p2 = %p, pl1 = %p, pl2 = %p!\n", p1, p2, pl1, pl2 );
  }

  return 0;
}
4

2 回答 2

6

ASLR 主要是随机化用户空间地址空间顶部到栈的距离,以及栈保留空间底部到第一个的距离mmap(这可能是动态链接器的映射)。任何进一步的随机化都会对虚拟内存空间产生严重的碎片化影响,因此会破坏需要制作大mmaps 的程序(例如 32 位机器上的 1-2 GB 映射)。

我已经看到一些 Linux 发行版发布了修补内核,这些内核对mmap. 其中一些甚至为您提供与为堆栈扩展保留的空间重叠的映射,然后当堆栈增长时,它会破坏您的映射(导致巨大的安全漏洞,比任何非随机地址分配可能造成的漏洞都要大) . 远离这些黑客。

于 2012-02-28T16:18:04.737 回答
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也不为零。)

于 2012-02-28T16:16:12.203 回答