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

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

заставляет программу выполнить инструкцию int3.

Программы, написанные на C и собранные с помощью gcc, имеют неисполняемые данные, стек и кучу, так почему программы, написанные на ассемблере, ведут себя по-другому?


person witosx    schedule 22.10.2011    source источник


Ответы (1)


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

Если вы скомпилируете, например. int foo() { return 1; } в сборку (с gcc -S foo.c), вы увидите следующее:

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

Для nasm синтаксис показан в раздел 8.9.2 руководства; вы хотите что-то вроде этого:

 section .note.GNU-stack noalloc noexec nowrite progbits

Примечание

Это необходимо сделать для каждого .o файла, который входит в исполняемый файл. Если какому-либо объектному файлу требуется исполняемый стек или данные, он устанавливается для всего сегмента.

person Employed Russian    schedule 22.10.2011
comment
Это работает, спасибо. Кстати, я нашел это: ссылка, а в разделе 7.9.2 elf Extensions to the В директиве SECTION указано, что секция .data по умолчанию имеет флаг noexec. Но даже явное написание noexec в коде с разделом .data не работает. Странный. - person witosx; 23.10.2011
comment
Не могли бы вы предоставить какой-либо источник, документирующий поведение GNU_STACK? Я видел, что вы можете передать -z noexecstack в ld, чтобы он вел себя так же... Но разве это не проблема загрузчика? загрузчик отображает раздел .data как исполняемый файл, когда он явно помечен как noexec. - person Marco; 27.07.2020
comment
@Marco: немного больше информации на Неожиданное разрешение на выполнение от mmap, когда файлы сборки включены в проект, включая ссылку на исходный код ядра Linux. . - person Peter Cordes; 27.07.2020
comment
Спасибо. Это вносит некоторую ясность. Я думаю, что понимаю причину этого: старые эльфы (до бита NX в современных арках) могли зависеть от наличия исполняемых данных, поскольку отключить их было невозможно. Таким образом, для обнаружения более новых эльфов загрузчик использует функцию исполняемого стека. Печально, что nasm не имеет флага для автоматического добавления. - person Marco; 27.07.2020
comment
Обратите внимание, что поведение недавно изменилось для Linux. ядро. В более новых ядрах разделы, скомпилированные с помощью nasm, больше не будут выполняться по умолчанию в x86_64. См. коммит - person Marco; 27.07.2020