有人可以指出gcc -D_FORTIFY_SOURCE=1
和-D_FORTIFY_SOURCE=2
之间的区别吗?我猜=2
更安全吗?我无法找到列出差异点的列表。
我还读到-D_FORTIFY_SOURCE=2
应与-O2
一起使用,否则并非所有功能都可用。此外,我还没有找到一个列表,详细说明回归。我特别感兴趣的是用-Os
进行编译,因为目标是没有那么多闪存的设备。
有关记录在哪里的任何提示都欢迎!
答案 0 :(得分:43)
从功能测试宏的手册页(man 7 feature_test_macros
)
_FORTIFY_SOURCE
(因为glibc 2.3.4)定义此宏会导致执行一些轻量级检查,以便在使用各种字符串和内存操作函数时检测一些缓冲区溢出错误(例如,
memcpy
,memset
,stpcpy
,{ {1}},strcpy
,strncpy
,strcat
,strncat
,sprintf
,snprintf
,vsprintf
,{{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.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
的{{1}}也很好,但是 通常当攻击者试图利用格式字符串时 漏洞,_("%s string %n")
将位于攻击者所能到达的地方 把它写进去。