Reputation: 177
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
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