Разница между 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 будет где-то, где злоумышленник может записать это.

Другие вопросы по тегам