Linux - 为什么每次运行程序时,程序断点指针(brk/sbrk)会不同?

6
我知道程序断点是Linux操作系统为一个进程分配的最高虚拟内存地址,因此标记了堆的最高地址。您可以通过调用sbrk( 0 )来获取程序断点的地址。
当我创建以下简单的程序时,每次运行时都会得到不同的结果:
#define _BSD_SOURCE
#include <stdio.h>
#include <unistd.h>

int main()
{
    printf( "system break: %p\n", sbrk( 0 ) );
    return 0;
}

例如,在我的电脑上:
$ ./sbrk
system break: 0x81fc000
$ ./sbrk
system break: 0x9bce000
$ ./sbrk
system break: 0x97a6000

我的理解是堆在虚拟内存中紧接着BSS段之上分配 - 我猜我期望它对于像这样的简单程序总是有相同的初始值。程序断点最初的位置是否存在某种随机化或其他因素?如果没有,为什么每次运行程序都不同?
2个回答

6

默认情况下,内核会随机化初始点,但是这个功能可以被禁用。以下是运行的代码(对于x86,在arch/x86/kernel/process.c):

unsigned long arch_randomize_brk(struct mm_struct *mm)
{
        unsigned long range_end = mm->brk + 0x02000000;
        return randomize_range(mm->brk, range_end, 0) ? : mm->brk;
}

此外,在这个 ELF 二进制文件加载器的函数中 (fs/binfmt_elf.c),你可以看到被调用的函数:
if ((current->flags & PF_RANDOMIZE) && (randomize_va_space > 1)) {
                current->mm->brk = current->mm->start_brk =
                        arch_randomize_brk(current->mm);
#ifdef CONFIG_COMPAT_BRK
                current->brk_randomized = 1;
#endif
}

5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接