0

I'm trying to allocate 0x4000 bytes in the heap by uses the brk system call. However when doing this, trying to set anything after 0x999 segfaults. This is what I'm using:

global _start

section .data
    heapStart: dq 0 ; Start of the heap

section .text
_start:
    mov rax, 12 ; Heap call
    mov rdi, 0
    syscall ; Get the base pointer

    mov QWORD [heapStart], rax

    lea rdi, [rax + 0x4000]
    mov rax, 12
    syscall ; Allocate 8000 bytes

    mov rdi, heapStart

    mov BYTE [rdi + 0x1000], 'b' ; Errors "SIGSEGV"
    
    mov rax, 60 ; exit
    mov rdi, 0 ; error code
    syscall

Why does this happen? And how can I set bytes over 0x999?

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Ari
  • 31
  • 4
  • 6
    You want `mov rdi, [heapStart]` not `mov rdi, heapStart` which loads the address of the variable, not its value. – Jester Sep 06 '21 at 21:27
  • 6
    Just as a hex reminder, the next number after `0x999` isn't `0x1000` but `0x99a`. The number preceding `0x1000` is `0xfff`. And your `0x4000` allocates not 8000 bytes but 16384. – Nate Eldredge Sep 06 '21 at 21:30
  • 1
    Memory protection works in chunks of 4k pages. Writing past the end of space you reserved in `.data` won't fault until you cross into an unmapped page. [Is it safe to read past the end of a buffer within the same page on x86 and x64?](https://stackoverflow.com/q/37800739). Err, I guess you didn't intend to offset relative to the address of `heapStart`, but rather to the return value of the 2nd brk syscall. [Basic use of immediates vs. square brackets in YASM/NASM x86 assembly](https://stackoverflow.com/q/10362511) covers that, the first dup is why it didn't crash with smaller offsets. – Peter Cordes Sep 06 '21 at 21:49

0 Answers0