进程生命周期审计需覆盖fork→exec→运行态变更→exit→wait全链路,分别捕获系统调用时间、PID/PPID、UID/GID、完整路径与参数、信号、退出码及回收行为,并结构化落盘以支持溯源与合规验证。

进程生命周期审计不是简单地“看一眼ps”,而是对进程从诞生到彻底消失的每一步关键动作做可追溯、可验证的记录。它面向安全合规、故障复盘和资源治理,核心在于捕获真实发生的系统调用事件,而非仅依赖状态快照。
创建阶段:fork()与exec()必须分离审计
一个新进程通常经历两个独立步骤:先 fork() 复制,再 exec() 加载新程序。审计需分别记录:
- fork() 调用时间、调用者 PID/PPID、子进程 PID、UID/GID —— 这是“谁启动了谁”的源头证据;
- exec() 系统调用的时间、完整路径(如 /bin/bash)、参数(注意是否被截断或敏感信息脱敏)、是否成功;
- 若只记录 fork() 而忽略 exec(),就无法区分“空壳子进程”和“真正执行业务的进程”,审计价值大幅下降。
运行中状态变更:关注调度与信号干预
进程在生命周期中会频繁切换状态(R/S/D/T/Z),但常规 ps 输出不可审计。真正可落盘的审计线索来自:
- SIGSTOP/SIGCONT 信号的发送者(通过 auditd 的 syscall=kill + a1=19/18 捕获);
- ptrace() 调用 —— 表明该进程正被调试或注入,属于高风险行为;
- setuid/setgid 等权限提升操作,需关联进程 PID 和调用前后的有效 UID;
- 避免只记录“进程在运行”,而要记录“谁在什么时间点触发了它的状态变化”。
退出与回收:僵尸与孤儿进程需显式标记
exit() 或异常终止后,进程进入“已终止但未回收”状态(Zombie),此时 task_struct 仍驻留内核。审计必须覆盖:
- exit_group() 系统调用的时间、退出码(exit_code)、退出信号(exit_signal);
- wait()/waitpid() 的调用方 PID、等待的子 PID、获取到的状态字(含 WIFEXITED/WEXITSTATUS 等);
- 若父进程未 wait,且子进程最终被 init(PID 1)收养并回收,audit 日志应体现该收养事件(常见于 systemd 环境);
- 长期存在的 Z 状态进程,是资源泄漏或父进程缺陷的直接证据,审计日志需支持按存活时长筛选。
审计数据落地:格式统一、不可篡改、带上下文
有效的生命周期审计日志不是零散的系统调用堆砌,需结构化并携带上下文:
- 每条记录含唯一 trace_id,串联同一进程的 fork→exec→signal→exit 全链路;
- 记录进程命令行(/proc/[pid]/cmdline)、当前工作目录(/proc/[pid]/cwd)、打开文件(/proc/[pid]/fd/)快照(可选,按策略采样);
- 日志写入需经 syslog-ng 或 auditd 直接落盘至只读分区,禁用纯内存缓冲;
- 建议启用 Linux audit subsystem 的规则:-a always,exit -F arch=b64 -S fork,clone,execve,exit_group,wait4,waitpid。











