有人能指出gcc -D_FORTIFY_SOURCE=1和-D_FORTIFY_SOURCE=2之间的区别吗?我猜=2更安全?我一直无法找到一个列表,列出逐点的区别。我还读到-D_FORTIFY_SOURCE=2应该和-O2一起使用,否则不是所有的特性都可用。同样在这里我还没有找到一个详细说明回归的列表。我特别感兴趣的是用-Os编译,因为目标是一个没有那么多闪存的设备。欢迎提供任何有关此文档位置的提示!
gcc -D_FORTIFY_SOURCE=1
-D_FORTIFY_SOURCE=2
=2
-O2
-Os
6uxekuva1#
来自功能测试宏(man 7 feature_test_macros)的手册页
man 7 feature_test_macros
_FORTIFY_SOURCE
定义此宏将导致执行一些轻量级检查,以检测在使用各种字符串和内存操作函数时的某些缓冲区溢出错误(例如,memcpy,memset,stpcpy,strcpy,strncpy,strcat,strncat,sprintf,snprintf,vsprintf,vsnprintf,gets,及其宽字符变体)。对于某些函数,检查自变量一致性;例如,当指定的标志包括**O_CREAT时,检查open是否已提供 mode 参数。并非所有问题都被检测到,只是一些常见情况。如果_FORTIFY_SOURCE设置为1,则使用编译器优化级别1(gcc -O1)或更高级别,执行不应更改符合标准的程序的行为的检查。将_FORTIFY_SOURCE**设置为2时,会添加更多的检查,但某些符合要求的程序可能会失败。一些检查可以在编译时执行(通过头文件中实现的宏逻辑),并导致编译器警告;其他检查在运行时发生,并且如果检查失败则导致运行时错误。使用此宏需要编译器支持,gcc从4.0版开始提供此支持。此外,文章Enhance application security with FORTIFY_SOURCE(2014年3月)说:
memcpy
memset
stpcpy
strcpy
strncpy
strcat
strncat
sprintf
snprintf
vsprintf
vsnprintf
gets
O_CREAT
open
gcc -O1
gcc
#include <string.h>
gcc -D_FORTIFY_SOURCE=2
本质上,_FORTIFY_SOURCE级别2更安全,但编译策略的风险略高;如果使用它,请确保对编译后的代码进行非常强大的回归测试,以证明编译器没有引入任何意外行为。
nnsrf1az2#
https://gcc.gnu.org/legacy-ml/gcc-patches/2004-09/msg02055.html比feature_test_macros(7)更详细。以下是相关摘录,为了清晰起见,略作编辑/重新格式化:例如,-D_FORTIFY_SOURCE=1和-D_FORTIFY_SOURCE=2之间的差异为
feature_test_macros(7)
-D_FORTIFY_SOURCE=1
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
var
将被认为是缓冲区溢出。另一个不同之处在于,对于-D_FORTIFY_SOURCE=2,仅当%n存储在只读存储器中时,才允许使用最常见的*printf系列函数的格式字符串(通常是字符串文字,X1 M9 N1 X的X1 M10 N1 X也可以),但是通常当攻击者试图利用格式字符串漏洞时,%n将位于攻击者可以写入的位置。
%n
*printf
2条答案
按热度按时间6uxekuva1#
来自功能测试宏(
man 7 feature_test_macros
)的手册页_FORTIFY_SOURCE
(自glibc 2.3.4起)定义此宏将导致执行一些轻量级检查,以检测在使用各种字符串和内存操作函数时的某些缓冲区溢出错误(例如,
memcpy
,memset
,stpcpy
,strcpy
,strncpy
,strcat
,strncat
,sprintf
,snprintf
,vsprintf
,vsnprintf
,gets
,及其宽字符变体)。对于某些函数,检查自变量一致性;例如,当指定的标志包括**O_CREAT
时,检查open
是否已提供 mode 参数。并非所有问题都被检测到,只是一些常见情况。如果
_FORTIFY_SOURCE
设置为1,则使用编译器优化级别1(gcc -O1
)或更高级别,执行不应更改符合标准的程序的行为的检查。将
_FORTIFY_SOURCE
**设置为2时,会添加更多的检查,但某些符合要求的程序可能会失败。一些检查可以在编译时执行(通过头文件中实现的宏逻辑),并导致编译器警告;其他检查在运行时发生,并且如果检查失败则导致运行时错误。
使用此宏需要编译器支持,
gcc
从4.0版开始提供此支持。此外,文章Enhance application security with FORTIFY_SOURCE(2014年3月)说:
gcc -D_FORTIFY_SOURCE=1
仅在编译时添加检查(某些标头对于#include <string.h>
是必需的)gcc -D_FORTIFY_SOURCE=2
还在运行时添加检查(检测到缓冲区溢出会终止程序)本质上,
_FORTIFY_SOURCE
级别2更安全,但编译策略的风险略高;如果使用它,请确保对编译后的代码进行非常强大的回归测试,以证明编译器没有引入任何意外行为。nnsrf1az2#
https://gcc.gnu.org/legacy-ml/gcc-patches/2004-09/msg02055.html比
feature_test_macros(7)
更详细。以下是相关摘录,为了清晰起见,略作编辑/重新格式化:
例如,
-D_FORTIFY_SOURCE=1
和-D_FORTIFY_SOURCE=2
之间的差异为对于
-D_FORTIFY_SOURCE=1
,不视为溢出(对象是整个
var
),而使用-D_FORTIFY_SOURCE=2
将被认为是缓冲区溢出。
另一个不同之处在于,对于
-D_FORTIFY_SOURCE=2
,仅当%n
存储在只读存储器中时,才允许使用最常见的*printf
系列函数的格式字符串(通常是字符串文字,X1 M9 N1 X的X1 M10 N1 X也可以),但是通常当攻击者试图利用格式字符串漏洞时,%n
将位于攻击者可以写入的位置。