Подтвердить что ты не робот

Почему данные и сегменты стека исполняются?

Я только что заметил, что моя простая программа имеет свои исполняемые файлы и сегменты стека. Я видел его в /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, имеют свои данные, стек и кучу неисполняемые, поэтому почему написанные на сборке ведут себя по-другому?

4b9b3361

Ответ 1

В современных Linux-системах компоновщик будет отмечать неисполняемый IFF стек/данные, все объекты, участвующие в ссылке, имеют специальный раздел "маркер" .note.GNU-stack.

Если вы скомпилируете, например, 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, который входит в исполняемый файл. Если для любого объектного файла требуется исполняемый стек или данные, он устанавливается для всего сегмента.