c - Linux 上的堆栈开始

标签 c linux memory stack-memory aslr

我认为我可以通过在 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/

相关文章:

c - 什么是网络套接字的文件描述符?以及如何得到它?

c - string.withCString 和 UnsafeMutablePointer(变异 : cstring) wrapped into a function

将 uint16_t 转换为 unsigned int

c - 在 C 中获取 Linux 中已经运行的进程的标准输出

linux - 在 Bash Cloud Shell 中映射 Azure 文件共享

JavaFX ImageView 内存泄漏

c - OMP 分析中的依赖性

linux - 如何在 Linux 中创建运行过程图

memory - Stm32f4内存跳转

javascript - 当浏览器窗口关闭时,表单/JavaScript 数据会发生什么?