smatch
时间轴
2026-05-21
init
Smatch 是一个专为 Linux 内核设计的静态分析工具,能深入追踪代码的执行路径,发现一些隐藏得很深的bug,比如空指针解引用、锁使用错误、资源泄漏等。参考文档:
编译 smatch
1 | # 安装依赖 |
kernel
Smatch 本质上会走 kernel build system, 所以必须能正确找到编译器和头文件, 因此如果需要交叉编译必须先设置环境变量。
1 | export ARCH=arm64 |
分析并构建数据库
1 | cd ~/repository/linux/linux-5.10.256 |
build_kernel_data.sh 会附加 --call-tree, --info, --spammy, --data=$DATA_DIR 参数调用 smatch_scripts/test_kernel.sh, 随后调用 smatch_data/db/create_db.sh 构建 smatch 数据库
smatch 并不强制需要构建数据库,但是构建数据库会更加强大, 一旦总数据库建成,下次再编译时,Smatch 就能通过查表知道:“printk 这个函数在整个内核里被调用了多少次”、“某个结构体指针在其他 C 文件里有没有被释放过”,从而实现史诗级的跨文件漏洞侦测。
运行 smatch 对 kernel 进行静态分析:运行 smatch 检查整个kernel
1 | ~/repository/linux/smatch-1.74/smatch_scripts/test_kernel.sh --data="$HOME/repository/linux/smatch-1.74/smatch_data" |
脚本参数
--endian:开启大端/小端字节序检查。--target "bzImage":指定编译目标(默认是 bzImage modules)。--log smatch_compile.warns: 指定编译日志输出文件--wlog smatch_warns.txt:自定义 Smatch 警告的输出文件名。
编译完成后,会在当前目录下生成两个文件:
smatch_compile.warns:完整的内核编译日志(含报错和警告)。smatch_warns.txt:纯粹的 Smatch 静态检查警告信息。
也可以只检查某个文件或文件夹下的代码
1 | ~/repository/linux/smatch-1.74/smatch_scripts/kchecker drivers/rpmsg/rpmsg_core.c |
smatch作者建议经常更新smatch数据库, 因为每次更新跨函数的检查会更准确
1 | ~/repository/linux/smatch-1.74/smatch_data/db/create_db.sh -p=kernel smatch_warns.txt |
smatch 在运行时会读取smatch_data中设置的一些规则, 在~/repository/linux/smatch-1.74/smatch.c中static char *get_data_dir(char *arg0)有相关逻辑:可以通过传递--data=/path/to/smatch_data指定
out-of-tree module
对于非kernel项目, 用以下方法构建数据库并分析
1 | export ARCH=arm64 |
--file-output每个文件输出一个结果--succeed表示即使出错也继续分析--call-tree表示开启跨函数调用分析--info表示更详细的分析日志--spammy表示更激进的检查
当用了 --file-output 参数后,smatch 默认不会把警告直接打印在终端的 stdout/stderr 上,而是会在你的代码同级目录下生成一堆隐藏的文本文件:
.hello_world.c.smatch(常规警告).hello_world.c.smatch.caller_info(如果你加了 --info 等参数)静态检查分析