gcc -D_强化_源=1和-D_强化_源=2之间的差异

zengzsys  于 2023-02-16  发布在  其他
关注(0)|答案(2)|浏览(132)

有人能指出gcc -D_FORTIFY_SOURCE=1-D_FORTIFY_SOURCE=2之间的区别吗?我猜=2更安全?我一直无法找到一个列表,列出逐点的区别。
我还读到-D_FORTIFY_SOURCE=2应该和-O2一起使用,否则不是所有的特性都可用。同样在这里我还没有找到一个详细说明回归的列表。我特别感兴趣的是用-Os编译,因为目标是一个没有那么多闪存的设备。
欢迎提供任何有关此文档位置的提示!

6uxekuva

6uxekuva1#

来自功能测试宏(man 7 feature_test_macros)的手册页

_FORTIFY_SOURCE(自glibc 2.3.4起)

定义此宏将导致执行一些轻量级检查,以检测在使用各种字符串和内存操作函数时的某些缓冲区溢出错误(例如,memcpymemsetstpcpystrcpystrncpystrcatstrncatsprintfsnprintfvsprintfvsnprintfgets,及其宽字符变体)。对于某些函数,检查自变量一致性;例如,当指定的标志包括**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更安全,但编译策略的风险略高;如果使用它,请确保对编译后的代码进行非常强大的回归测试,以证明编译器没有引入任何意外行为。

nnsrf1az

nnsrf1az2#

https://gcc.gnu.org/legacy-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系列函数的格式字符串(通常是字符串文字,X1 M9 N1 X的X1 M10 N1 X也可以),但是通常当攻击者试图利用格式字符串漏洞时,%n将位于攻击者可以写入的位置。

相关问题