-fno-stack-protector有什么用途?

42

我写了一个C语言应用程序,现在我正试图了解在编译时使用-fno-stack-protector命令的目的是什么。对于我的特定应用程序而言,是否使用此命令并不影响其防护缓冲区溢出。

我在网上看到说-fstack-protector-fno-stack-protector命令分别启用和禁用栈破坏保护器,但如果我自己编译应用程序,那么如何先启用保护器呢?这个命令的使用可能取决于应用程序所运行的系统吗?

5个回答

29

在标准/原始的GCC中,默认情况下未启用栈保护器。然而,一些Linux发行版已经打了补丁,使GCC默认开启它。在我看来,这是相当有害的,因为它会破坏编译任何未链接到标准用户空间库的东西的能力,除非Makefile明确禁用栈保护器。它甚至会破坏Linux内核构建过程​​,但这些发行版添加了额外的Hack来检测正在构建内核并禁用它。


2
根据定义,任何在默认启用堆栈保护的系统上编译的东西都会与使用堆栈保护构建的库链接,因为它们反过来也将在已启用堆栈保护的系统上进行编译。 - tbert
1
我假设您正在处理我的回答的第二部分(有关为何存在问题的评论),如果是这样,在这种情况下,答案是否定的。任何不打算作为主机用户空间生态系统的一部分运行的代码都不会链接到主机的任何库。(例如,内核不会链接到任何用户空间库。其他示例可能是引导加载程序代码、旨在被dynrec/JIT模拟器读取并用作模板的模块等)。 - R.. GitHub STOP HELPING ICE
我并没有谈论内核空间,而是用户空间;JIT编译不是使用C编译器完成的;所以,我必须问一下,在用户空间开启堆栈保护有什么问题,除了可能需要在Linux内核的编译参数中设置“-fno-stack-protector”之外? - tbert
1
我的JIT示例是,可以不为每个可能的ISA编写代码生成逻辑,而是编写JIT将使用的C代码单元,将其编译为ELF .o文件,并将它们用作数据由JIT进行汇编,只需最少的ISA特定知识。也许你不喜欢我的例子,但肯定可以想出其他例子。基本上,在任何使用编译器作为独立实现的情况下,堆栈保护都是错误的(尽管可以通过省略-lssp并提供自己的__stack_chk_fail来使其正常工作)。 - R.. GitHub STOP HELPING ICE
1
我的观点是关于什么出了问题,它强制要求使用 C 编译器作为自由实现的每个程序都包含逻辑来检查 ssp 是否默认开启,并且如何将其关闭到构建系统中。而且下次发行版再次使用默认的 GCC 配置时,相同的问题将会重复出现。如果“-ffreestanding”可以防止默认开启 ssp,那么这就不是一个问题了。 - R.. GitHub STOP HELPING ICE
“…一些Linux发行版已经修补了GCC,使其默认开启。” - 栈保护现在是标准的安全功能。虽然可能存在一些特殊情况(例如使用“-ffreestanding”的自定义发行版),但通常应该启用它们。关闭它们应该会触发安全缺陷。 - jww

19
如果你使用-fstack-protector进行编译,那么在栈上会分配更多的空间,在函数进入和返回时,代码将设置检查并实际检查是否在函数内部覆盖了栈,因此会产生一些额外的开销。
这将对您的应用程序产生影响。如果启用了此选项,它将快速防止堆栈溢出攻击。只有当您的代码中没有函数调用时,它才不会影响您的程序(而由于通常编写main(),它是由启动代码调用的函数,所以它将影响您的程序)。但是,堆栈溢出攻击并不是唯一可能使用的攻击,因此它并非万灵药。但是,它是一种成本有限的有用保护。
该保护不取决于系统本身;它取决于您正在使用的编译器版本,但仅此而已。

1
-fstack-protector 还重新排列堆栈布局,以便更容易检测到Smash攻击。 - jww
@jww 是的,我注意到字符串(char[])的内存是在任何其他整数之前分配的。因此,溢出它不会覆盖整数。 - Hritik

3

堆栈保护器是由编译器生成并嵌入程序中的代码。它不是被程序调用的外部程序或系统调用。


1

与默认编译器设置匹配的选项有用的时候包括:

  • 当您使用可能具有复杂配置的构建系统时,您希望进行微调。与其弄清楚在一堆makefile中可能会选择使用fstack-protector(例如),不如让您轻松地传递附加选项,这些选项只需添加到选项列表的末尾即可。如果GCC在选项集中看到fstack-protectorfno-stack-protector,则命令行上最后一个选项将生效。

  • 另一种情况下,这种方法可能很方便(但似乎不适用于-fstack-protector),就是当您有一个选项可以打开一堆“子选项”时。例如,设置-O2会打开一系列-fxxx优化选项,您可能大部分时间都想使用-O2,但不想使用GCC的严格别名优化。因此,您可以指定-fno-strict-aliasing将该特定选项设置回其默认设置。(注意:此情况实际上等同于上面的情况)


0

有三个可能需要关闭这个功能的原因:

  • 您正在构建一个共享库,其中可能会影响其他函数对栈的假设。
  • 您关注性能。
  • 您想构建易受攻击的软件。这在Capture The Flag(CTFs)之类的比赛中经常发生,例如,如果您想构建Protostar来展示否则不会易受攻击的漏洞利用。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接