背景: 开发过程中发现自己的某个进程被莫名其妙的杀死了,概率性的,不好查。想知道是被哪个进程给误杀了
Linux kernel 版本: linux-3.18.20
audit 版本: audit-1.7.18
首先 Kernel 要支持 audit,要看 linux-3.18.20/kernel 目录下有没有 audit 相关的 .c 文件
audit.c
audit_tree.c
audit_watch.c
auditfilter.c
auditsc.c
有了这些文件就需要修改配置文件,让它们被编译进内核
参考 https://patchwork.kernel.org/patch/7800051/ 拉到网页最后的补丁
发现这个补丁文件还是存在问题,因为它没有打开 HAVE_ARCH_AUDITSYSCALL 这一项,所以最后 AUDITSYSCALL 也没被打开
直接用我如下这个补丁文件: enable_audit.patch
--- a/init/Kconfig 2019-09-20 09:13:06.856735962 +0800
+++ b/init/Kconfig 2019-09-23 17:38:40.490129265 +0800
@@ -317,16 +317,11 @@
auditing without CONFIG_AUDITSYSCALL.
config HAVE_ARCH_AUDITSYSCALL
- bool
+ bool "HAVE_ARCH_AUDITSYSCALL"
config AUDITSYSCALL
bool "Enable system-call auditing support"
depends on AUDIT && HAVE_ARCH_AUDITSYSCALL
- default y if SECURITY_SELINUX
- help
- Enable low-overhead system-call auditing infrastructure that
- can be used independently or with another kernel subsystem,
- such as SELinux.
config AUDIT_WATCH
def_bool y
cd linux-3.18.20
patch -p1 < ../enable_audit.patch
make menuconfig 里面选中这3项
[*] Auditing support
[*] HAVE_ARCH_AUDITSYSCALL
[*] Enable system-call auditing support
检查看看 .config 这几个都是 y 就可以了
CONFIG_AUDIT=y
CONFIG_HAVE_ARCH_AUDITSYSCALL=y
CONFIG_AUDITSYSCALL=y
CONFIG_AUDIT_WATCH=y
CONFIG_AUDIT_TREE=y
编译 kernel,烧写 uImage 镜像文件到开发板上
下载源码包和补丁文件: audit-1.7.18.tar.gz + audit-1.7.18-cross.patch + audit-1.7.18-sys_stat_h.patch
http://repository.timesys.com/buildsources/a/audit/audit-1.7.18/
注意: audit-1.7.18-cross.patch 是交叉编译所需的补丁文件,audit-1.7.18-sys_stat_h.patch 是解决编译错误的补丁
解压源码包
tar -zxf audit-1.7.18.tar.gz
打补丁
cd audit-1.7.18
patch -p1 < ../audit-1.7.18-cross.patch
patch -p1 < ../audit-1.7.18-sys_stat_h.patch
配置
./configure CC=arm-hisiv600-linux-gcc --host=arm-hisiv600-linux --prefix=/home/admin/audit_out/
我的开发板是32位系统,所以这个地方需要设置一下(注意要加上大括号括起来)
audit-1.7.18/lib/libaudit.c audit_detect_machine() 函数里面添加这句: strcpy(uts.machine, "i386");
int audit_detect_machine(void)
{
struct utsname uts;
if (uname(&uts) == 0) {
strcpy(uts.machine, "i386");
return audit_name_to_machine(uts.machine);
}
return -1;
}
编译
make
生成可执行文件、库文件、配置文件
make install
拷贝可执行文件到开发板的 /bin 和 /sbin 目录
拷贝库文件到开发板的 /lib 目录
拷贝配置文件到开发板的 /etc 目录
cp -rfp /home/admin/audit_out/sbin/* /sbin
cp -rfp /home/admin/audit_out/bin/* /bin
cp -rfp /home/admin/audit_out/lib/libaudit.so* /lib
cp -rfp /home/admin/audit_out/lib/libauparse.so* /lib
cp -rfp /home/admin/audit_out/etc/audit/ /etc
mkdir -p /var/log/audit
chown root /etc/audit/auditd.conf
chown root /sbin/audispd
chmod 0750 /sbin/audispd
reboot 开发板
-f 表示前台运行,会有log打出,方便debug(等你解决bug之后可以把要把 -f 去掉,即变为后台运行 auditd)
auditd -f
注意: auditd 是后台守护进程,负责监控记录
可以看看 auditd 有没有跑起来
ps | grep audit
400 root 0:00 auditd
403 root 0:00 [kauditd]
409 root 0:00 grep audit
这一句可以看到当前 auditd 的状态,如果看到 enabled=1 则说明 auditd 已经跑起来了
auditctl -s
注意: auditctl 是配置规则的工具
加上这个规则后,再用 kill 杀死一个进程就可以看到是谁干的了(我发现这里必须得加 -k 给规则起个名字,才能成功添加规则)
auditctl -a exit,always -S kill -k my_monitor_kill
这一句可以查看当前存在的规则有哪些
auditctl -l
试验
pkill -9 xxxx.bin
看看 /var/log/audit/audit.log 有没有相应的 log 信息
type=SYSCALL msg=audit(231.260:3): arch=40000028 syscall=37 per=800000 success=yes exit=0 a0=10c a1=9 a2=9 a3=0 items=0 ppid=341 pid=547 auid=4294967295 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=ttyAMA0 ses=4294967295 comm="pkill" exe="/bin/busybox" key="my_monitor_kill"
type=OBJ_PID msg=audit(231.260:3): opid=268 oauid=-1 ouid=0 oses=-1 ocomm="xxxx.bin"
type=UNKNOWN[1327] msg=audit(231.260:3): proctitle=706B696C6C002D39006170705F68646D69
ppid=341 pid=547,表示是哪个 pid 发出的 pkill 命令
opid=268,表示是哪个 pid 被杀掉了
ps | grep 341
341 root 0:00 -sh
651 root 0:00 grep 341
可以看出 341 这个 pid 是 shell 进程,即命令行发出的 pkill 信号杀掉了 xxxx.bin