Met*_*est 5 c linux gcc x86-64 aslr
我希望由于地址空间布局随机化(ALSR),从另一个进程分叉的进程将在调用时返回不同的地址mmap.但正如我发现的那样,事实并非如此.为此目的,我做了以下测试程序.返回的所有地址malloc对于父级和子级完全相同.需要注意的是,malloc对于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;
}
Run Code Online (Sandbox Code Playgroud)
ASLR主要随机化从用户空间地址空间顶部到堆栈的距离,以及从堆栈保留空间底部到第一个空间的距离mmap(可能是动态链接器的映射).任何进一步的随机化都会对虚拟内存空间产生严重的碎片效应,从而破坏需要制作大型mmaps的程序(例如,在32位机器上进行1-2 GB映射).
我已经看到一些Linux发行版附带修补内核,它们对返回的地址执行更多随机化mmap.它们中的一些甚至会给你映射重叠与为堆栈保留的空间扩展,然后当堆栈增长时,它会破坏你的映射(导致一个巨大的安全漏洞,比任何非随机地址分配都要大得多) .远离这些黑客.
您无法重新随机化子级的地址空间 - 所有指针都必须被修改,这在技术上是不可能的(运行时环境甚至不知道数据的哪一部分是指针)。
因此,您看到的结果是预期的,分叉中的子项在分叉时拥有其父地址空间的精确副本,包括其虚拟地址布局。
您需要进行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
Run Code Online (Sandbox Code Playgroud)
(并确保/proc/sys/kernel/randomize_va_space也不为零。)