1

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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Rodrigo
  • 167
  • 2
  • 9
  • 3
    Um, the `xor` instruction is modifying the byte at `_start+1`. In a `text` section, that byte is read-only, whereas in a `data` section, it is writeable. It seems that you already know enough information to answer your own question, so I'm kind of confused. – Cody Gray - on strike Jul 01 '16 at 19:04

1 Answers1

4

[_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.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
  • Ok, so I understand why I don't get seg-fault in section .data. But now I got confused- why do I get segfault at section .text? why is it a problem to access the first byte of [_start+1] in this section? – Rodrigo Jul 01 '16 at 19:46
  • 2
    @Rodrigo: (revised previous comment): You said in your question that you know `.text` is mapped read-only. What happens when an instruction tries to write to a page that's mapped read-only? – Peter Cordes Jul 01 '16 at 20:41
  • Related: a duplicate for non-shellcode questions with arrays in .text accidentally: [x86\_64 Assembly - Segfault when trying to edit a byte within an array in x64 assembly](https://stackoverflow.com/q/45005078) – Peter Cordes Oct 15 '21 at 22:13