如何用Clang编译启用CFI的.so文件?附示例及问题排查
CFI Sanitizer 启用指南(C语言)
示例C代码(add.c)
要触发CFI的检查逻辑,代码中需要包含函数指针调用场景(CFI在C中主要针对函数指针的类型安全检查):
#include <stdio.h> // 定义函数指针类型 typedef int (*add_func_t)(int, int); // 导出可见的加法函数 __attribute__((visibility("default"))) int add(int a, int b) { return a + b; } // 导出可见的函数指针调用函数 __attribute__((visibility("default"))) int call_add(add_func_t func, int a, int b) { return func(a, b); }
正确编译命令
针对共享库的CFI启用命令需要明确指定CFI子类型(针对C的函数指针检查用cfi-icall),同时保留必要的LTO和可见性控制参数:
clang -fPIC -flto -fsanitize=cfi-icall -fvisibility=hidden -shared add.c -o libadd.so
为什么之前未发现CFI符号?
- 缺少触发场景:如果代码中没有函数指针调用、虚函数(C++)等CFI需要检查的控制流,Clang不会生成CFI相关符号
- 未指定CFI子类型:默认的
-fsanitize=cfi包含多个检查项,但在纯C代码中只有cfi-icall会生效,明确指定子类型能确保生成对应检查逻辑 - LTO依赖:CFI的检查逻辑是在链接时(LTO阶段)生成的,缺少
-flto参数会导致CFI完全不生效
验证CFI符号存在
使用以下命令查看生成的CFI相关符号:
readelf -s libadd.so | grep cfi # 或 nm -D libadd.so | grep cfi
你会看到类似__cfi_icall、__cfi_check的符号,说明CFI已正确启用。
内容的提问来源于stack exchange,提问作者Vamsi Simhadri
相关产品推荐
相关产品推荐

