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]
.
rsp
as specified here https://mcmap.net/q/23281/-why-does-this-code-crash-with-address-randomization-on – Ophthalmoscopesub rsp, ##
to reserve space for local variables (as long as they take up no more than 128 bytes below RSP) and your function doesn't call other functions.. If you need more space then you adjust RSP to account for it. You can access memory beyond that but you have to concern yourself with Linux guard pages. – Gyneco[stack]
? – Ophthalmoscopersp, 0x1000 * PAGE_SIZE
that is below the fixed mapping, but segfault also occurred. No manually created mappings exist below. – OphthalmoscopeMAP_FIXED_NOREPLACE
or just a normal non-NULL hint address without either FIXED flag. (mmap
won't randomly pick it, and it might be reserved with a mechanism that stops it from being allocated withoutMAP_FIXED
) – PittelMAP_FIXED_NOREPLACE
macro declaration in thesys/mman.h
neither in theman mmap
. The only hint was specified here. I use kernel 4.18.0. Tying to manually add the flag tommap
arguments also resulted in segfault. – Ophthalmoscopemmap
function in glibc is just a thin wrapper for the system call; it doesn't need to understand the flags. – Pittel