Я бьюсь головой об стену с этим.
В моем проекте, когда я выделяю память с mmap
помощью mapping ( /proc/self/maps
), видно, что это читаемая и исполняемая область, несмотря на то, что я запрашивал только читаемую память.
Изучив strace (который выглядел хорошо) и другие средства отладки, я смог определить единственное, что, по-видимому, позволяет избежать этой странной проблемы: удаление файлов сборки из проекта и оставление только чистого C. (что ?!)
Итак, вот мой странный пример, я работаю над Ubunbtu 19.04 и gcc по умолчанию.
Если вы компилируете целевой исполняемый файл с файлом ASM (который является пустым), то mmap
возвращает читаемую и исполняемую область, если вы строите без этого, он будет вести себя правильно. Смотрите вывод, /proc/self/maps
который я встроил в мой пример.
example.c
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
int main()
{
void* p;
p = mmap(NULL, 8192,PROT_READ,MAP_ANONYMOUS|MAP_PRIVATE,-1,0);
{
FILE *f;
char line[512], s_search[17];
snprintf(s_search,16,"%lx",(long)p);
f = fopen("/proc/self/maps","r");
while (fgets(line,512,f))
{
if (strstr(line,s_search)) fputs(line,stderr);
}
fclose(f);
}
return 0;
}
example.s : это пустой файл!
Выходы
С включенной версией ASM
VirtualBox:~/mechanics/build$ gcc example.c example.s -o example && ./example
7f78d6e08000-7f78d6e0a000 r-xp 00000000 00:00 0
Без включенной версии ASM
VirtualBox:~/mechanics/build$ gcc example.c -o example && ./example
7f1569296000-7f1569298000 r--p 00000000 00:00 0
-Wa,--noexecstack
.Ответы:
Linux имеет домен исполнения под названием
READ_IMPLIES_EXEC
, которое вызывает все страницы , выделенные сPROT_READ
также быть предоставленыPROT_EXEC
. Эта программа покажет вам, включена ли она для себя:Если вы скомпилируете это вместе с пустым
.s
файлом, вы увидите, что он включен, но без него он будет отключен. Начальное значение этого происходит из метаинформации ELF в вашем двоичном файле . Естьreadelf -Wl example
. Вы увидите эту строку, когда скомпилируете без пустого.s
файла:Но этот, когда вы скомпилировали с ним:
Обратите внимание,
RWE
а не простоRW
. Причина этого заключается в том, что компоновщик предполагает, что ваши файлы сборки требуют read-implies-exec, если явно не указано, что они этого не делают, а если какой-либо части вашей программы требуется read-implies-exec, то он включен для всей вашей программы. , Файлы сборки, которые компилирует GCC, сообщают, что в этом нет необходимости, с этой строкой (вы увидите это, если будете компилировать-S
):Вставьте эту строку
example.s
, и она будет сообщать компоновщику, что он тоже не нужен, и тогда ваша программа будет работать так, как ожидалось.источник
.o
файлы! Но в любом случае, я думаю, что это механизм, которыйgcc -zexecstack
использует, и почему он делает не просто стек, а все исполняемым.-Wa,--noexecstack
. Я думаю, что это очень противный острый край. Тихая потеря nx-стеков должна быть уязвимостью безопасности. Люди Binutil должны это исправить..note.GNU-stack,"",@progbits
объяснили смысл / логику строки - сейчас она непрозрачна, что эквивалентно «эта волшебная строка символов вызывает этот эффект», но строка явно выглядит так, как будто имеет какой-то вид семантика.В качестве альтернативы для изменения ваших сборочных файлов с помощью специфических для GNU вариантов директив раздела, вы можете добавить
-Wa,--noexecstack
в командную строку сборочные файлы сборки. Например, посмотрите, как я делаю это в муслеconfigure
:https://git.musl-libc.org/cgit/musl/commit/configure?id=adefe830dd376be386df5650a09c313c483adf1a
Я полагаю, что по крайней мере некоторые версии clang с интегрированным ассемблером могут требовать, чтобы он был передан как
--noexecstack
(без-Wa
), поэтому ваш скрипт configure, вероятно, должен проверить оба и посмотреть, что принято.Вы также можете использовать
-Wl,-z,noexecstack
во время ссылки (вLDFLAGS
), чтобы получить тот же результат. Недостаток этого состоит в том, что это не помогает, если ваш проект создает статические.a
файлы библиотеки ( ) для использования другим программным обеспечением, так как тогда вы не контролируете параметры времени соединения, когда он используется другими программами.источник