gcc -D_FORTIFY_SOURCE = 1和-D_FORTIFY_SOURCE = 2之间的差异

时间:2012-11-22 17:24:17

标签: security gcc glibc

有人可以指出gcc -D_FORTIFY_SOURCE=1-D_FORTIFY_SOURCE=2之间的区别吗?我猜=2更安全吗?我无法找到列出差异点的列表。

我还读到-D_FORTIFY_SOURCE=2应与-O2一起使用,否则并非所有功能都可用。此外,我还没有找到一个列表,详细说明回归。我特别感兴趣的是用-Os进行编译,因为目标是没有那么多闪存的设备。

有关记录在哪里的任何提示都欢迎!

2 个答案:

答案 0 :(得分:43)

从功能测试宏的手册页(man 7 feature_test_macros

  

_FORTIFY_SOURCE (因为glibc 2.3.4)

     

定义此宏会导致执行一些轻量级检查,以便在使用各种字符串和内存操作函数时检测一些缓冲区溢出错误(例如,memcpymemsetstpcpy,{ {1}},strcpystrncpystrcatstrncatsprintfsnprintfvsprintf,{{1其宽字符变体)。对于某些函数,检查参数一致性;例如,当指定的标志包含 vsnprintf 时,会检查gets是否已提供模式参数。并非所有问题都被检测到,只是一些常见的情况。

     

如果 open 设置为1,编译器优化级别为1( O_CREAT )及更高级别,则检查不应更改执行合规程序的行为。

     

_FORTIFY_SOURCE 设置为2时,会添加更多检查,但某些符合规定的程序可能会失败。

     

某些检查可以在编译时执行(通过头文件中实现的宏逻辑),并导致编译器警告;其他检查在运行时进行,如果检查失败,则会导致运行时错误。

     

使用此宏需要编译器支持,自4.0版以来gcc -O1可用。

此外,文章Enhance application security with FORTIFY_SOURCE(2014年3月)说:

  • _FORTIFY_SOURCE仅在编译时添加检查(某些标头是必需的gcc
  • gcc -D_FORTIFY_SOURCE=1还会在运行时添加检查(检测到的缓冲区溢出会终止程序)

基本上,#include <string.h>级别2更安全,但编译策略风险稍大;如果您使用它,请确保您对已编译的代码进行了非常强大的回归测试,以证明编译器未引入任何意外行为。

答案 1 :(得分:11)

http://gcc.gnu.org/ml/gcc-patches/2004-09/msg02055.htmlfeature_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的{​​{1}}也很好,但是   通常当攻击者试图利用格式字符串时   漏洞,_("%s string %n")将位于攻击者所能到达的地方   把它写进去。