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

wit*_*osx 17 linux assembly nasm memory-mapping

我刚刚注意到我的简单程序的数据和堆栈段是可执行的.我在/ 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
Run Code Online (Sandbox Code Playgroud)

然后

nasm -f elf64 prog.asm
ld -o prog prog.o
./prog
Run Code Online (Sandbox Code Playgroud)

导致prog执行int3指令.

用C语言编写并用gcc构建的程序使其数据,堆栈和堆不可执行,那么为什么那些用汇编编写的程序会以不同的方式运行?

Emp*_*ian 18

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

如果你编译int foo() { return 1; }成汇编(with gcc -S foo.c),你会看到:

    .section    .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)

因为nasm,语法显示在手册的第7.9.2节中 ; 你想要这样的东西:

 section .note.GNU-stack noalloc noexec nowrite progbits
Run Code Online (Sandbox Code Playgroud)

注意

必须对进入可执行文件的每个 .o文件执行此操作.如果任何目标文件需要可执行堆栈或数据,则为整个段设置它.

  • @Marco:[当程序集文件包含在项目中时,来自 mmap 的意外执行权限](/sf/ask/4078232581/)有更多信息,包括指向 Linux 内核源代码的链接。 (2认同)
  • 请注意,Linux 内核的行为[最近更改](https://lore.kernel.org/kernel-hardening/20200327064820.12602-1-keescook@chromium.org/)。对于较新的内核,默认情况下,使用“nasm”编译的部分将不再在 x86_64 中可执行。[参见提交](https://github.com/torvalds/linux/commit/9fccc5c0c99f238aa1b0460fccbdb30a887e7036) (2认同)