为什么数据和堆栈段是可执行的?

我刚刚注意到,我的简单程序的数据和堆栈段可执行。 我在/ proc / [pid] / maps中看到了,简单的代码证实了它。

例如:

; prog.asm section .data code: db 0xCC ;int3 section .text global _start _start: jmp code mov rax, 60 ; sys_exit mov rdi, 0 syscall 

然后

 nasm -f elf64 prog.asm ld -o prog prog.o ./prog 

导致prog执行int3指令。

用C编写的,用gcc构build的程序的数据,堆栈和堆是不可执行的,那么为什么写在汇编中的程序却以不同的方式运行呢?

在现代Linux系统上,链接器将标记堆栈/数据不可执行的IFF所有参与链接的对象都有一个特殊的“标记”部分.note.GNU-stack

如果你编译例如int foo() { return 1; } int foo() { return 1; }到汇编(与gcc -S foo.c ),你会看到这样的:

  .section .note.GNU-stack,"",@progbits 

对于nasm ,语法如本手册第7.9.2节所示; 你想要这样的东西:

  section .note.GNU-stack noalloc noexec nowrite progbits 

注意

对于每个进入可执行文件的.o文件都必须完成这个工作。 如果任何目标文件需要可执行的堆栈或数据,那么它被设置为整个段。