使用kprobe测试时,会发现有些接口无法使用。
比如do_execveat_common这个接口,在另一个版本接近的内核源码中可以看到,但实际注册提示找不到这个接口。
有可能是因为内核源码不完全一致,也可能是因为有的接口在编译时被优化掉了?
1、bpftrace -l
所以bpftrace -l这个查询接口就十分重要。
#bpftrace -l 'kprobe:*exec*'
会列出很多exec相关的支持kprobe功能的接口,最终配合源码,选择跟踪bprm_execve这个接口。
2、bpftrace使用kprobe跟踪
#!/usr/bin/env bpftrace
#include <linux/fs.h>
//kprobe:do_execveat_common
kprobe:bprm_execve
{
printf("filename:%s\n", str(((struct filename *)arg2)->name));
}
结果就是可以跟踪系统通过exec启动的二进制程序。
执行效果如下:
/home/leiyanjie/test/bpftrace # bpftrace exec.bt
Attaching 1 probe...
filename:/bin/sh
filename:/bin/tr
filename:/bin/cat
filename:/bin/sh
filename:/bin/tr
filename:/bin/cat
filename:/taihang/bin/regcmd
filename:/taihang/bin/regcmd
3、bpftrace增加过滤条件
如果想只看某个特殊的二进制程序呢?那就可以比对filename和期望的二进制程序路径就可以了。
#!/usr/bin/env bpftrace
#include <linux/fs.h>
//kprobe:do_execveat_common
kprobe:bprm_execve
{
if(str(((struct filename *)arg2)->name) == "/taihang/bin/regcmd") {
printf("filename:%s\n", str(((struct filename *)arg2)->name));
}
}
执行效果如下:
/home/leiyanjie/test/bpftrace # bpftrace exec.bt
Attaching 1 probe...
filename:/taihang/bin/regcmd
filename:/taihang/bin/regcmd
filename:/taihang/bin/regcmd
filename:/taihang/bin/regcmd
filename:/taihang/bin/regcmd
filename:/taihang/bin/regcmd
4、count()
count()的值需要记录到一个map,一般是分类计数的时候使用。
比如我们统计每个进程执行过多少次bprm_execve接口。
test/bpftrace # bpftrace -e "k:bprm_execve { @count[comm] = count(); }"
Attaching 1 probe...
^C
@count[crond]: 1
@count[libvirtd]: 1
@count[kworker/u32:1]: 1
@count[python3]: 2
@count[python]: 2
@count[taihang_sdpcie_]: 3
@count[ioemu_cli]: 4
@count[bash]: 4
@count[ipmitool]: 6
@count[sh]: 11
@count[node_exporter]: 18