In the x86-64 System V ABI it is specified that the space behind the $rsp - 128
is the so-called red zone which is not touched by any signal handlers. On my machine
$ ulimit -s
8192
I expected there is only 2 pages in the stack. So I wrote the following program to test till which size red zone can expand:
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
So I expected the program always fails. But the program sometimes fails with SEGV
, sometimes finishes fine.
The behavior is exactly as what MAP_GROWSDOWN
documents:
This flag is used for stacks. It indicates to the kernel virtual memory system that the mapping should extend downward in memory. The return address is one page lower than the memory area that is actually created in the process's virtual address space. Touching an address in the "guard" page below the mapping will cause the mapping to grow by a page. This growth can be repeated until the mapping grows to within a page of the high end of the next lower mapping, at which point touching the "guard" page will result in a
SIGSEGV
signal.
As discussed in this question mappings created with MAP_GROWSDOWN
and PROT_GROWSDOWN
does not grow that way:
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
QUESTION: Combining the reasoning above is it true that the only mapping that uses MAP_GROWSDOWN
is the main thread's [stack]
mapping ?