Разница между gcc -D_FORTIFY_SOURCE=1 и -D_FORTIFY_SOURCE=2
Может кто-то указать на разницу между gcc -D_FORTIFY_SOURCE=1
а также -D_FORTIFY_SOURCE=2
? Похоже =2
безопаснее? Я не смог найти список, в котором перечислены различия по пунктам.
Я также читал, что -D_FORTIFY_SOURCE=2
следует использовать с -O2
иначе не все функции будут доступны. Также здесь я не нашел список, который бы детально указывал регрессии. Мне было бы особенно интересно собрать с -Os
так как целью является устройство с не так много флэш-памяти.
Любые намеки на то, где это задокументировано, приветствуются!
2 ответа
Со страницы руководства для макросов тестирования функций (man 7 feature_test_macros
)
_FORTIFY_SOURCE
(начиная с версии 2.3.4)Определение этого макроса приводит к выполнению некоторых легких проверок для обнаружения некоторых ошибок переполнения буфера при использовании различных функций обработки строк и памяти (например,
memcpy
,memset
,stpcpy
,strcpy
,strncpy
,strcat
,strncat
,sprintf
,snprintf
,vsprintf
,vsnprintf
,gets
и их широкие символьные варианты). Для некоторых функций проверяется согласованность аргументов; например, проверяется, чтоopen
был предоставлен аргумент режима, когда указанные флаги включаютO_CREAT
, Не все проблемы обнаружены, только некоторые распространенные случаи.Если
_FORTIFY_SOURCE
установлен на 1, с уровнем оптимизации компилятора 1 (gcc -O1
) и выше, выполняются проверки, которые не должны изменять поведение соответствующих программ.С
_FORTIFY_SOURCE
При значении 2 добавлена дополнительная проверка, но некоторые соответствующие программы могут завершиться неудачей.Некоторые проверки могут выполняться во время компиляции (с помощью логики макросов, реализованной в заголовочных файлах) и приводить к предупреждениям компилятора; другие проверки выполняются во время выполнения и приводят к ошибке во время выполнения, если проверка не удалась.
Для использования этого макроса требуется поддержка компилятора, доступная с
gcc
с версии 4.0.
Кроме того, в статье " Повышение безопасности приложений с помощью FORTIFY_SOURCE" (март 2014 г.) говорится:
gcc -D_FORTIFY_SOURCE=1
добавляет проверки только во время компиляции (некоторые заголовки необходимы как#include <string.h>
)gcc -D_FORTIFY_SOURCE=2
также добавляет проверки во время выполнения (обнаруженное переполнение буфера завершает программу)
По существу, _FORTIFY_SOURCE
уровень 2 более безопасен, но представляет собой немного более рискованную стратегию компиляции; если вы используете его, убедитесь, что у вас есть очень строгие регрессионные тесты для вашего скомпилированного кода, чтобы доказать, что компилятор не ввел неожиданное поведение.
http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.html более подробно, чем feature_test_macros(7)
,
Вот соответствующий отрывок, слегка отредактированный / переформатированный для ясности:
Разница между
-D_FORTIFY_SOURCE=1
а также-D_FORTIFY_SOURCE=2
например, дляstruct S { struct T { char buf[5]; int x; } t; char buf[20]; } var;
С
-D_FORTIFY_SOURCE=1
,strcpy (&var.t.buf[1], "abcdefg");
не считается переполнением (объект является целым
VAR
), в то время как с-D_FORTIFY_SOURCE=2
strcpy (&var.t.buf[1], "abcdefg");
будет считаться переполнением буфера.
Другое отличие состоит в том, что с
-D_FORTIFY_SOURCE=2
,%n
в формате строки наиболее распространенных*printf
Семейные функции разрешены, только если они хранятся в постоянной памяти (обычно строковые литералы,gettext
"s_("%s string %n")
тоже хорошо), но обычно, когда злоумышленник пытается использовать уязвимость строки формата,%n
будет где-то, где злоумышленник может записать это.