I have just noticed that my simple program has its data and stack segments executable.
I saw it in /proc/[pid]/maps, and simple code confirmed it.
For example:
; prog.asm
section .data
code: db 0xCC ;int3
section .text
global _start
_start:
jmp code
mov rax, 60 ; sys_exit
mov rdi, 0
syscall
then
nasm -f elf64 prog.asm
ld -o prog prog.o
./prog
causes prog to execute int3 instruction.
Programs written in C and built with gcc have their data, stack and heap non-executable, so why those written in assembly behave in a different manner?
On modern Linux systems, the linker will mark stack/data non-executable IFF all objects that participate in the link have a special "marker" section
.note.GNU-stack.If you compile e.g.
int foo() { return 1; }into assembly (withgcc -S foo.c), you’ll see this:For
nasm, the syntax is shown in section 8.9.2 of the manual; you want something like this:Note
This has to be done for every
.ofile that goes into the executable. If any object file needs executable stack or data, then it’s set for the entire segment.