Linux内核中破损的KRETPROBES与OPTIMIZER简史
在开发Linux内核运行时防护工具LKRG过程中发现:
- 自内核5.8起KRETPROBES机制失效(已在后续内核修复)
- 自内核5.5起OPTIMIZER未充分执行优化任务
KPROBES与FTRACE技术背景
Linux内核提供两种钩子框架:
-
K*PROBES(2004年引入):
- KPROBES:可在任意内核指令插入断点
- JPROBES:通过镜像原理访问函数参数(2017年弃用)
- KRETPROBES:在函数入口/返回路径执行自定义例程
-
FTRACE(2008年引入):
- 通过编译时注入"long-NOP"指令实现动态跳转
- 性能开销低于K*PROBES
LKRG的运行时防护机制
作为类似微软PatchGuard的技术,LKRG通过KRETPROBES实现:
- 内核运行时完整性检查
- 凭证/SECCOMP/命名空间等任务完整性验证
- 需处理FTRACE与KPROBES共存场景(“FTRACE-based KPROBES”)
问题复现与分析
问题1:KRETPROBES失效(自5.8内核)
关键变更点:
|
|
根本原因:
exc_int3()
调用nmi_enter()
设置NMI标记pre_handler_kretprobe()
检测到NMI状态后放弃处理- 相关修复补丁已提交至稳定分支
问题2:OPTIMIZER优化不足(自5.9内核)
新发现现象:
- GCC在函数末尾生成INT3指令填充
- 内核链接器脚本变更导致(commit 7705dc85)
|
|
优化失败逻辑:
|
|
修复方案:
- 已由Masami Hiramatsu提交补丁区分填充INT3与调试断点
技术影响
通过LKRG开发发现的这两个问题:
- 揭示了中断处理逻辑变更对调试子系统的影响
- 暴露了编译器行为变化与内核探针优化的兼容性问题
- 相关修复已合并至主线内核
(全文完)