I'm running some experiments with stack and the following got me stuck.
It can be seen that Linux has initial [stack]
mapping 132KiB
in size. In case of ulimit -s unlimited
we can expand the stack any further if we adjust rsp
accordingly. So I set ulimit -s unlimited
and ran the following program:
PAGE_SIZE equ 0x1000
;mmap staff
PROT_READ equ 0x01
PROT_WRITE equ 0x02
MAP_ANONYMOUS equ 0x20
MAP_PRIVATE equ 0x02
MAP_FIXED equ 0x10
;syscall numbers
SYS_mmap equ 0x09
SYS_exit equ 0x3c
section .text
global _start
_start:
; page alignment
and rsp, -0x1000
; call mmap 0x101 pages below the rsp with fixed mapping
mov rax, SYS_mmap
lea rdi, [rsp - 0x101 * PAGE_SIZE]
mov rsi, PAGE_SIZE
mov rdx, PROT_READ | PROT_WRITE
mov r10, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED
mov r8, -1
mov r9, 0
syscall
sub rsp, 0x80 * PAGE_SIZE
mov qword [rsp], -1 ; SEGV
mov rax, SYS_exit
mov rdi, 0
syscall
Even in spite of adjusting the rsp
it segfaults anyway. I don't really get the point. I manually created a fixed mapping at the address rsp - 0x101 * PAGE_SIZE
101 pages below the rsp
.
My expectation was that it would not interfere with expanding the stack (rsp - 0x80
in my case) till we hit the fixed mapping rsp - 0x101 * PAGE_SIZE
.
Btw, If I remove MAP_FIXED
from the mapping it is not honored and no segfault occurs (as expected). Here is the strace output:
mmap(0x7ffe4e0fe000, 4096, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x1526e3f3a000
But MAP_FIXED
does the job:
mmap(0x7ffd8979c000, 4096, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7ffd8979c000
UPD: The segfault is not triggered if lea rdi, [rsp - 0x101 * PAGE_SIZE]
is replaced with lea rdi, [rsp - 0x200 * PAGE_SIZE]
.