我认为我可以通过在 main 中获取变量的地址并向上舍入到页面边界来开始我的进程堆栈(考虑到我的堆栈会向下增长)。
我将此与 /proc/self/maps
报告的边界进行了比较,它总是偏离 1、2 或 3 页(每页 4096 字节),从来没有不同的偏移量。每次运行的差异都会有所不同,下面的(杂乱的,不是简约的)管道中使用的这个 C 程序展示了差异。
stacksz.c:
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <stdio.h>
#define CAT "cat /proc/XXXXXXXXXXX/maps"
#define CATP "cat /proc/%ld/maps"
#define MASK ((sizeof(char)<<12)-1)
int main()
{
uintptr_t top = (uintptr_t)&top + MASK & ~MASK;
char cat[sizeof CAT];
sprintf(cat,CATP,(long)getpid());
if(system(cat)) return 1;
printf(" %lx stack\n", top);
return 0;
}
bash 管道:
gcc stacksz.c && echo "$(( $(./a.out |grep stack |tr '-' ' ' |cut -d' ' -f2 |sed 's/^/0x/'|tr '\n' -|sed 's/-$//') ))"
我很好奇是否有人可以解释这种现象。
机器是 Linux 精度 4.15.0-43-generic#46-Ubuntu SMP x86_64
。
我在 1000 次运行中得到以下偏移分布:
4096 195
8192 490
12288 315
最佳答案
ASLR 首先完全随机化虚拟内存中的堆栈位置。但它做得更多:它还随机化了相对于堆栈映射顶部的堆栈指针!
来自linux源代码:
unsigned long arch_align_stack(unsigned long sp)
{
if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
sp -= get_random_int() % 8192;
return sp & ~0xf;
}
这里,如果 ASLR 处于事件状态,则堆栈指针减少 0-8192 字节,然后对齐 16 字节。这解释了1-3页的可变偏移量。
关于c - Linux 上的堆栈开始,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54543603/