SystemTap
SystemTap是一款Linux跟踪探测(trace/probe)工具,可收集Linux运行信息,用于性能诊断和问题排查等。SystemTap不需要每次都对内核修改、编译、安装、重启等繁杂冗余的操作,通过其自定义的脚本语言,即可编写功能丰富强大的探测模块,动态载入内核,对系统进行监控,获取指定信息。
SystemTap可以监控系统调用、内核函数及其他发生在内核的事件(event),当事件触发时,运行指定处理例程(handler)。
原理
SystemTap基于Kprobes实现,Kprobes允许在内核代码任意地址设置断点,当断点触发时,运行指定的处理例程。Kprobes有两种探测类型:kprobes和kretprobes,kprobes可以探测内核任意指令,kretprobes探测函数返回。当注册一个kprobe时,会拷贝一份探测指令,然后将指令的第一个字节替换成断点指令(如int3),断点触发时运行指定处理函数,然后运行原始指令。当注册一个kretprobe,会在探测函数入口点注册一个常规的kprobe,当函数调用时,会获取返回地址,然后将返回地址替换成一个跳转地址(trampoline address),当函数返回时,运行跳转地址,此时处理函数执行,然后再运行原始返回地址。
SystemTap的运行分以下5个步骤:
- parse,解析脚本,转换成解析树(parse tree),这个阶段还会进行预处理,语法语义检查。
- elaboration,解析脚本中符号和引用,依赖tapsets(预编写的脚本库)和调试信息。
- translate, 将第2步输出转换成C代码。
- build,将C代码编译成内核模块。
- run,加载内核模块并运行。
stap命令完成前4步,第5步由staprun和stapio完成。
安装
各Linux发行版如Ubuntu、CentOS等,都提供了SystemTap安装包,直接通过包管理命令安装即可,这里采用源码编译方式安装。
从SystemTap Releases下载最新版源码,编译安装,依赖的第三方工具及开发包直接通过包管理命令安装即可。
$ cd systemtap-3.2 |
SystemTap借助调试信息来确定内核探测点地址,需要调试版内核,这里重新编译Linux-4.14内核。
$ cd linux-4.14-debuginfo |
可以修改Makefile
中的EXTRAVERSION
为EXTRAVERSION = -debuginfo
,这样安装后内核版本为4.14.0-debuginfo
,以便和非调试版内核做区分。
$ cp ../linux-4.14/.config ./ |
配置内核参数:
General setup ---> |
配置完后,检查.config
配置文件中以下参数都已配置:
CONFIG_DEBUG_INFO |
编译安装内核:
$ make -j 20 |
重启系统,检查SystemTap是否安装成功:
$ uname -r |
使用
SystemTap安装好后,自带的示例脚本位于/usr/local/share/systemtap/examples/
,编写脚本可以作为参考。tapsets位于/usr/local/share/systemtap/tapset/
。
SystemTap脚本语言借鉴了dtrace和awk,SystemTap脚本以.stp
作为文件扩展名,包含的探测点采用如下格式编写:
probe event {statement} |
这里以探测sshd进程的系统调用统计为例,了解SystemTap脚本的使用。
global syscalllist |
这里脚本运行10s,输出结果:
$ sudo stap sshd_profile.stp |
调用exit()退出,也可通过Ctrl-c
退出。
SystemTap会缓存脚本转换后的C语言和内核模块,如果脚本没有更改,再次运行时不必重新构建,直接使用之前的。
也可显示保存构建的内核模块,供后续直接使用,-m
指定内核模块名,-p4
表示处理到第4阶段停止:
$ sudo stap -v -m sshd_profile.ko -p4 sshd_profile.stp |
staprun
运行编译好的模块:
$ sudo staprun sshd_profile.ko |
Cuckoo沙箱Linux检测引擎就使用了SystemTap,可以参见下一篇博客Cuckoo沙箱Linux检测引擎。
参考: