-D_FORTIFY_SOURCE=1编译无效果?咨询生效条件及相关问题
关于-D_FORTIFY_SOURCE的常见问题解答
为什么编译后checksec显示FORTIFY为No、加固函数数量为0?
可能存在以下几个原因:
- 目标缓冲区大小无法被编译器确定:如果你的
strcpy调用中,目标是动态分配的内存(比如malloc返回的指针)、或者是未指定大小的指针,编译器无法在编译期获取缓冲区的准确大小,也就无法将strcpy替换为加固版本__strcpy_chk。比如下面的代码就无法被加固:
而如果目标是固定大小的数组,编译器就能识别并替换:char *dest = malloc(10); strcpy(dest, "long string that overflows");char dest[10]; strcpy(dest, "long string that overflows"); - 编译选项或环境问题:确保没有使用禁用Fortify的选项(比如
-fno-fortify-source),同时确认你的gcc版本和系统libc支持Fortify(RedHat系系统默认的glibc版本通常满足要求)。另外,部分旧版本的checksec可能存在检测逻辑的局限性,可通过查看二进制符号表(用nm ftest | grep chk)确认是否存在加固函数。 - 优化等级未达标:Fortify依赖编译器的数据流分析,必须开启
-O1及以上的优化等级(你用了-O2是符合要求的,但如果编译时不小心覆盖了优化等级也会失效)。
-D_FORTIFY_SOURCE=1何时生效?
满足以下条件时,该选项才会起作用:
- 开启优化等级-O1及以上:无优化时,编译器无法完成缓冲区大小的静态分析,也就无法替换加固函数。
- 编译器能确定缓冲区大小:目标函数(如
strcpy、memcpy)的源/目标缓冲区大小必须在编译期可被编译器推导,比如固定大小的栈数组、全局数组,或者通过sizeof能明确获取大小的对象。 - 使用支持Fortify的C标准库:比如glibc 2.3及以上版本,RedHat系发行版默认提供的libc均支持该特性。
代码中无目标函数时,gcc会尝试加固吗?
不会。Fortify的核心逻辑是扫描代码中特定的不安全函数调用,在满足条件的情况下将其替换为对应的加固版本。如果代码中没有strcpy、memcpy等目标函数,编译器不会执行任何Fortify相关的处理,也不会在二进制中生成加固相关的符号或逻辑。
内容的提问来源于stack exchange,提问作者Kiran
相关产品推荐
相关产品推荐

