bpftrace各维度捕捉SIGKILL信号
创始人
2024-05-22 00:31:58
0

一、问题

Ftrace 和 bpftrace中都有两个现成的脚本execsnoop、killsnoop, 我经常用他们从外部(不去读代码)观察几个关系紧密的进程之间是如何相互配合的,比如用execsnoop追踪一个大的系统(往往有多个进程)是如何逐一启动的,用killsnoop看他们相互之间信号的发送(进程间交互的一种方式)。
killsnoop是从tracepoint角度写的,今天我准备从各个角度重写此功能,包括:

  1. 用户空间追踪kill executable
  2. 用户空间追踪libc
  3. 发信号端内核空间追踪
  4. 接受信号端内核空间追踪

二、用户空间追踪kill executable

系统管理员一般使用/usr/bin/kill -9 xxx的方式去结束某进程,这样我们只要使用uprobe hook到main函数或其它函数然后把参数打出来即可。
为了简单直接对main下手,而且只考虑kill -9 xxx这种参数。不过出人意料的是,/usr/bin/kill竟然是strip的,没有main符号。

[root]# file /usr/bin/kill
/usr/bin/kill: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=2eaa68ee706e53cb99b1f07f6508dae7656c5a61, stripped

所以只好用offset

[root]# objdump -D /usr/bin/kill |grep 00000000000022f0 -A10
00000000000022f0 <.text>:22f0:       f3 0f 1e fa             endbr6422f4:       41 57                   push   %r1522f6:       66 0f ef c0             pxor   %xmm0,%xmm022fa:       41 56                   push   %r1422fc:       41 55                   push   %r1322fe:       41 54                   push   %r122300:       55                      push   %rbp2301:       89 fd                   mov    %edi,%ebp2303:       bf 06 00 00 00          mov    $0x6,%edi2308:       53                      push   %rbx

随便从上面选一个offset 0x2301

[root]# bpftrace -e 'struct argvarr {long a1; long a2; long a3;} uprobe:/usr/bin/kill:0x2301 {$tar=((struct argvarr*)reg("si"))->a3; $sig=((struct argvarr*)reg("si"))->a2; printf("%-6d(%s) -> %s, sig:%s", pid, comm, str($tar), str($sig));}'
Attaching 1 probe...
ERROR: Could not resolve address: /usr/bin/kill:0x2301

遇到不能解析地址的错误,根据文档加上unsafe即可

[root]# sleep 1000 &
[1] 2293884
[root]# kill -9 2293884
[root]# bpftrace -e 'struct argvarr {long a1; long a2; long a3;} uprobe:/usr/bin/kill:0x2301 {$tar=((struct argvarr*)reg("si"))->a3; $sig=((struct argvarr*)reg("si"))->a2; printf("%-6d(%s) -> %s, sig:%s", pid, comm, str($tar), str($sig));}' --unsafe
Attaching 1 probe...
WARNING: Could not determine instruction boundary for uprobe:/usr/bin/kill:8961 (binary appears stripped). Misaligned probes can lead to tracee crashes!
2293895(kill) -> 2293885, sig:-9

sig:-9 看着不顺的,自己改改吧。当然这种方式不能追踪直接调用kill函数的情况。

三、用户空间追踪libc

即使/usr/bin/kill也是最终调用的libc中的kill系统函数,所以hook libc能撒出更大的网。
首先查下libc在哪?

[root@]# ldd /usr/bin/killlinux-vdso.so.1 (0x00007ffdf93fe000)libc.so.6 => /lib64/libc.so.6 (0x00007f3bb35a2000)/lib64/ld-linux-x86-64.so.2 (0x00007f3bb3b70000)
[root@]# ls -l /lib64/libc.so.6
lrwxrwxrwx. 1 root root 12 Mar 11  2021 /lib64/libc.so.6 -> libc-2.28.so

然后查看kill的函数原型,两个参数分别是pid和sig_no,

#include 
int kill(pid_t pid, int sig);

所以,这个大网根据调用约定可以这样编写

bpftrace -e 'uprobe:/lib64/libc-2.28.so:kill {printf("%d(%s) -> %d, sig:%d\n", pid, comm, reg("di"), reg("si"));}'

bpftrace还给我们提供了快速访问参数的方便:argN

bpftrace -e 'uprobe:/lib64/libc-2.28.so:kill {printf("%d(%s) -> %d, sig:%d\n", pid, comm, arg0, arg1);}'

结果如下:

[root@jun perf-tools]# bpftrace -e 'uprobe:/lib64/libc-2.28.so:kill {printf("%d(%s) -> %d, sig:%d\n", pid, comm, arg0, arg1);}'
Attaching 1 probe...
2261306(bash) -> 2319005, sig:9

四、发信号端内核空间追踪

内核中有个tracepoint - sys_enter_kill,如果读过bpftrace中的样例killsnoop.bt, 就能知道内核中有这么个tracepoint。
如果不知道,也可以按关键词kill盲猜,猜出个大概后查看参数详情。

[root@]# bpftrace -l |grep kill
tracepoint:syscalls:sys_enter_kill
[root@]# bpftrace -lv sys_enter_kill*
tracepoint:syscalls:sys_enter_killint __syscall_nrpid_t pidint sig

结果如下(略掉了kill -9.。。。) :

[root@jun bpftrace]# bpftrace -e 'tracepoint:syscalls:sys_enter_kill {printf("%d(%s) -> %d, sig:%d\n", pid, comm, args->pid, args->sig);}'
Attaching 1 probe...
2258577(bash) -> 2300678, sig:9

五、接受信号端内核空间追踪

以上三种办法都是在发送端截获,信号接收端也是一种办法。Google了下内核在接收端是如何处理SIGKILL的,如有兴趣请参考这儿。
直接对do_group_exit下手,并额外打印了内核调用栈:

[root]# bpftrace -lv do_group_exit*
kfunc:do_group_exitint exit_code
kprobe:do_group_exit
[root]# bpftrace -e 'kprobe:do_group_exit {printf("pid:%-6d(%s) Got sig:%d, ks:%s, us:%s\n", pid, comm, reg("di"), kstack(), ustack());}'pid:2283764(sleep) Got sig:9, ks:do_group_exit+1get_signal+344do_signal+54exit_to_usermode_loop+137do_syscall_64+408entry_SYSCALL_64_after_hwframe+101
, us:0x7fe1a96f3d68

通过内核调用栈,能清晰的看到接收端处理SIGKILL的过程。而且也能看出在上层get_signal、do_signal下probe也是可行的。

相关内容

热门资讯

在干部选拔任用中为他人谋取利益... 在干部选拔任用中为他人谋取利益,并收受财物;利用职务影响低价购房;目无法纪,指使他人打探案情……7月...
纵使世态炎凉,但有你的地方就有... 纵使世态炎凉,但有你的地方就有光的意思这句话的大概意思是,就算世界全是势力,灰暗,但有你在的地方就是...
日本首席贸易谈判代表与美国商务...   随着7月9日更高关税生效的最后期限临近,日本首席贸易谈判代表 赤泽亮正与美国商务部长霍华德·卢特...
小伙脖子肿痛开刀取出7颗瓜子 转自:今晚报 【#小伙脖子肿痛开刀取出7颗瓜子#】#儿时...
雷军:小米YU7 全国58城7...   炒股就看金麒麟分析师研报,权威,专业,及时,全面,助您挖掘潜力主题机会! 新京报贝壳财经讯(记...
中国石化全资子公司新增一项23... (转自:快查一企业中标了)快查APP显示,中国石化相关公司中国石化青岛石油化工有限责任公司于2025...
一地通报:李某某、程某等9名教... 本文来自微信公众号“大象新闻”辽宁日报·辽望客户端7月5日消息,为贯彻落实中共中央办公厅、国务院办公...
AI耗电引发碳信用狂欢,看科技...   Hehson财经ESG评级中心提供包括资讯、报告、培训、咨询等在内的14项ESG服务,助力上市公...
第三十一届兰洽会张掖市签约67... 中国青年报客户端讯(中青报·中青网记者马富春)7月5日,第三十一届兰洽会张掖市招商引资推介暨重点项目...
马斯克就是否应成立新政党发起投... 来源:@央视财经微博 【#马斯克就是否应成立新政党发起投...