Rodrigo
Rodrigo

Reputation: 177

Code works when run from section .data, but segmentation faults in section .text

Why doesn't the following code give a segmentation fault?

global _start
section .data 

_start:
    mov ecx, 3
    xor byte[_start+1], 0x02
    mov eax, 1
    mov ebx, 2
    int 80h

I expected it to segfault at the same place (line marked with a comment) as when the same code is run in the .text section:

global _start
section .text  ; changed from data to text

_start:
    mov ecx, 3
    xor byte[_start+1], 0x02   ; ******get segmentation fault here
    mov eax, 1
    mov ebx, 2
    int 80h           

Now, I know that section .data is for read-write, and section .text is for read only.
But why would it matter when I try to access illegal memory address?

For the example here, I expected to get segmentation fault also at section .data, in the same place that I got it in section .text.

Upvotes: 1

Views: 422

Answers (1)

Peter Cordes
Peter Cordes

Reputation: 365951

[_start+1] is clearly not an illegal address. It's part of the 5 bytes encoding mov ecx, 3. (look at objdump -Mintel -drw a.out to see disassembly with the hex machine code).

IDK why you think there would be a problem writing to an address in .data where you've defined the contents. It's more common to use pseudo-instructions like db to assemble bytes into the data section, but assemblers will happily assemble instructions or db into bytes anywhere you put them.


The crash you'd expect from the .data version is from _start being mapped without execute permission but thanks to surprising defaults in the toolchain, programs with asm source files often end up with read-implies-exec (like gcc -zexecstack) unless you take precautions to avoid that:

If you applied that section .note.GNU-stack noalloc noexec nowrite progbits change, code fetch from RIP=_start would fault.


The version that tries to write to the .text section of course segfaults because it's mapped read-only.

Upvotes: 4

Related Questions