What is the use of -fno-stack-protector?
我已经用C语言编写了一个应用程序,并且试图了解-fno-stack-protector命令在编译时的目的是什么。对于我的特定应用程序,无论是否使用此命令,在防止缓冲区溢出方面都没有区别。
我已经在线阅读了-fstack-protector和-fno-stack-protector命令分别启用和禁用堆栈粉碎保护程序,但是如果我自己编译应用程序,那么如何预先启用该保护程序?该命令的用法是否取决于应用程序在哪个系统上运行?
在标准/常规GCC中,堆栈保护器默认情况下处于关闭状态。但是,某些Linux发行版已修补GCC,以默认将其打开。在我看来,这是相当有害的,因为它会破坏编译未与标准用户空间库链接的任何内容的能力,除非Makefile专门禁用了堆栈保护程序。它甚至会破坏Linux内核的构建,除了带有此hack的发行版向GCC添加了额外的hack,以检测到正在构建内核并禁用了它。
- 顾名思义,在默认情况下启用了堆栈保护的系统上编译的任何东西都不会链接到使用堆栈保护构建的库吗,因为它们反过来又会在启用了堆栈保护的系统上编译?
-
我假设您正在处理答案的第二部分(有关为什么会有问题的评论),如果是,在这种情况下,答案是否定的。任何不打算作为主机用户空间生态系统一部分运行的代码都不会与主机的任何库链接。 (例如,内核未与任何用户空间库链接。其他示例包括引导加载程序代码,打算由dynrec / JIT仿真器读取并用作模板的模块等)。
-
不是在谈论内核空间,而是用户空间。 JIT编译不是使用C编译器完成的;因此,我不得不问,除了可能必须在Linux内核的编译args中设置" -fno-stack-protector"之外,在用户区中打开堆栈保护还有什么问题?
-
我的JIT示例是,可以为每个可能的ISA编写代码生成逻辑,而不是编写JIT将在C语言中使用的代码单元,编译为ELF .o文件,然后将它们用作要组装的数据。具有最少的ISA特定知识的JIT。也许您不喜欢我的例子,但是可以肯定有人提出来。基本上,在将编译器用作独立实现的任何情况下,堆栈保护器都是错误的(尽管可以通过省略-lssp并提供自己的__stack_chk_fail使其工作)。
-
关于中断的观点是,它迫使使用C编译器作为独立实现的每个程序都包括检查ssp默认情况下是否打开以及如何将其关闭的逻辑。下一次发行版会针对默认的GCC配置进行破解时,同样的问题将再次发生。如果-ffreestanding阻止ssp在默认情况下处于打开状态,那么就不会有这样的问题。
-
" ...某些Linux发行版已修补GCC以默认将其打开。"-堆栈保护器现在是标准的安全功能。尽管可能会有一些极端情况(例如使用-ffreestanding的自定义发行版),但通常应该启用它们。关闭它们会触发安全缺陷。
如果使用-fstack-protector进行编译,则在代码设置检查后,实际上将检查您是否在在函数中已覆盖堆栈。
这将对您的应用程序有所帮??助。如果启用,它将迅速阻止堆栈溢出攻击。仅当您的代码中没有函数调用时,它才会使程序不受影响(并且由于您通常编写main(),并且该函数由启动代码调用,因此它将对您的程序产生影响)。但是,堆栈溢出攻击不是唯一可以使用的攻击,因此它不是万能药。但这是有用的保护,而且成本有限。
保护本身不依赖于系统;这取决于您使用的编译器的版本,仅此而已。
-
-fstack-protector还会重新排列堆栈布局,以使其更容易检测到崩溃。
-
@jww是的,我观察到字符串(char [])的内存在任何其他整数之前分配。因此,溢出不会覆盖int。
堆栈保护器是由编译器生成并置于程序中的代码。这不是您的程序调用的外部程序或系统调用。
您可能要关闭此功能的原因有三个,
-
您正在建立一个共享库,这可能很重要,而其他功能则对堆栈进行了假设。
-
您担心性能。
-
您要构建易受攻击的软件。这在Capture The Flag(CTF)之类的情况下经常发生,例如,如果您要构建Protostar来演示利用本来不会受到攻击的漏洞。
与默认编译器设置匹配的选项可能有用的时间包括:
-
当您使用可能具有要调整的复杂配置的构建系统时。不必弄清楚在makefile迷宫中的哪个位置(例如),可以选择使用fstack-protector,它可以让您轻松地传递附加的选项,这些选项可以简单地添加到选项列表的末尾。如果GCC在选项集中同时看到fstack-protector和fno-stack-protector,则命令行上的最后一个是生效的选项。
-
另一回事这类事情可能很方便(但是,这似乎不适用于-fstack-protector)是当您有一个可以打开一堆"子选项"的选项时。例如,设置-O2会打开许多??-fxxx优化选项,您可能想在大多数情况下使用-O2,但不希望GCC进行严格的别名优化。因此,您可以指定-fno-strict-aliasing将该特定选项设置回其默认设置。 (注意:这种情况实际上与上面的情况等效)