【发布时间】:2019-11-16 19:41:09
【问题描述】:
在x86-64 System V ABI 中指定$rsp - 128 后面的空间是所谓的红色区域,没有被任何信号处理程序触及。在我的机器上
$ ulimit -s
8192
我预计堆栈中只有 2 页。所以我写了下面的程序来测试红色区域可以扩大到多大:
PAGE_SIZE equ 0x1000
SYS_exit equ 0x3C
section .text
global _start
_start:
lea rcx, [rsp - 0x1f * PAGE_SIZE]
mov rax, rsp
loop:
sub rax, PAGE_SIZE
mov qword [rax], -1
cmp rax, rcx
jne loop
mov rax, SYS_exit
mov rdi, 0x20
所以我预计程序总是会失败。但该程序有时会因SEGV 而失败,有时完成得很好。
行为与MAP_GROWSDOWN 记录的完全一样:
此标志用于堆栈。它向内核表示虚拟 映射应该在内存中向下扩展的内存系统。这 返回地址比实际的内存区域低一页 在进程的虚拟地址空间中创建。触摸地址 映射下方的“守卫”页面将导致映射增长 页面。这种增长可以重复,直到映射增长到 在下一个较低映射的高端的一页内,其中 点触“守卫”页面将产生
SIGSEGV信号。
正如所讨论的,使用MAP_GROWSDOWN 和PROT_GROWSDOWN 创建的in this question 映射不会以这种方式增长:
volatile char *mapped_ptr = mmap(NULL, 4096,
PROT_READ | PROT_WRITE | PROT_GROWSDOWN,
MAP_GROWSDOWN | MAP_ANONYMOUS | MAP_PRIVATE,
-1, 0);
mapped_ptr[4095] = 'a'; //OK!
mapped_ptr[0] = 'b'; //OK!
mapped_ptr[-1] = 'c'; //SEGV
问题:结合上面的推理,唯一使用MAP_GROWSDOWN的映射是主线程的[stack]映射吗?
【问题讨论】:
-
红色区域始终是 RSP 当前值下方的 128 个字节。它根本不基于堆栈的大小。
-
@MichaelPetch
The red zone is always the 128 bytes- 是不是同一个红区 Raymond Chen discussed? -
请注意,
ulimit内置以 1024 字节为增量打印大小。所以当ulimit -s打印 8192 时,就意味着你的堆栈限制是 8MiB -- 2048 页。 -
由于没有标记操作系统,需要注意的是Windows没有红色区域。
-
与
sub rax, 4096相比,为什么循环如此复杂?我认为你通过每次重做乘法来做同样的事情,但它更难遵循。
标签: assembly x86-64 mmap callstack red-zone