Linux kprobes是否会被内核临时禁用?场景排查与检测方法问询
Kprobes 未触发导致命名空间变更监控误判的问题排查
问题描述
我通过在 wake_up_new_task()、do_exit()、begin_new_exec()、unshare() 和 setns() 上挂载 kprobes 来监控非法任务命名空间变更,但针对 timedated、upowerd 等部分 systemd 服务,kprobes 并非总能被触发,导致命名空间变更被遗漏、出现误判。此前已通过 BPF 映射中的 all_probes_attached 标志解决了探针挂载时服务启动的场景问题,但仍存在误判。想请教:
- kprobes 在挂起/恢复、休眠或内核热补丁期间是否会被临时禁用?
- 能否通过 BPF 或用户态检测该情况?
回答
1. kprobes 在特定系统状态下的行为
- 挂起/休眠/恢复阶段:kprobes 不会被主动禁用,但存在触发失效的可能。系统进入挂起/休眠时,内核会冻结大部分用户态进程和部分内核线程,依赖进程调度触发的 kprobes(比如关联用户态进程触发的内核函数的探针)会暂时停止工作。恢复后 kprobes 会自动恢复触发,但如果休眠期间有命名空间变更操作(极少发生,因为进程被冻结),可能出现遗漏;另外,部分内核临界区路径在休眠/恢复过程中会跳过 kprobes 执行,避免干扰内核状态。
- 内核热补丁期间:kprobes 会被临时禁用。内核热补丁(如 kpatch、livepatch)需要修改内核函数代码,而 kprobes 依赖在函数入口插入断点实现,热补丁操作会先移除相关 kprobes,完成补丁后再重新挂载。此过程中目标函数的 kprobes 处于失效状态,若此时有命名空间变更操作,就会被遗漏。
2. 检测 kprobes 失效的方法
BPF 侧检测
- 触发次数监控:在 BPF 程序中为每个目标 kprobes 维护触发计数器,通过
tracepoint:sched:sched_switch或 BPF 定时器定期检查计数器更新情况。如果unshare()、setns()等关键探针长时间无触发记录,结合系统状态判断探针是否失效。 - 挂载状态映射:扩展现有
all_probes_attached映射,增加单个探针的挂载状态标记。通过bpf_kprobe_attach的返回值判断挂载是否成功,用户态定期读取该映射,若发现探针状态变为未挂载,可触发告警或重新挂载。
用户态检测
- 读取内核 debug 文件:开启
CONFIG_DEBUG_FS后,内核提供/sys/kernel/debug/kprobes/list文件,记录所有已挂载 kprobes 的状态。用户态程序可定期解析该文件,检查目标 kprobes 是否存在且活跃。 - 监控热补丁事件:通过监听 systemd 的
org.freedesktop.kernel.livepatchD-Bus 事件,或读取/sys/kernel/livepatch目录文件,判断是否有热补丁正在应用。若检测到热补丁操作,可暂停监控逻辑,待补丁完成后重新验证探针状态。 - 监控休眠/挂起事件:通过监听
systemd-logind的PrepareForSleepD-Bus 事件,或读取/sys/power/state文件,在系统进入休眠前记录监控状态,恢复后重新检查探针状态,同时结合进程冻结/解冻事件补查可能遗漏的变更。
补充建议
针对 systemd 服务的探针失效问题,还可以:
- 改用 tracepoints 替代部分 kprobes:比如命名空间相关的
tracepoint:namespace:ns_set、tracepoint:sched:sched_process_exec等,这些内核原生 tracepoint 稳定性更高,不受热补丁或临界区路径影响。 - 增强 BPF 错误处理:在 BPF 程序中通过
bpf_printk或环形缓冲区输出错误日志,当探针挂载或触发失败时,及时将信息同步到用户态,辅助排查具体失效场景。
内容的提问来源于stack exchange,提问作者patraulea
相关产品推荐
相关产品推荐

