本页目录
Live Patching
覆盖: kernel livepatch (KLP) → ftrace-based → atomic replace → 状态一致性模型 → 实时内核 内核版本: 4.0 ~ 6.x (主线), 企业版 (RHEL 7+)
概述
Live patching 允许在不重启内核的情况下修复内核函数——适用于关键安全修复 (CVE) 和小逻辑 bug。核心原理:在正在运行的函数入口放一个 ftrace trampoline,跳转到新函数;然后逐个检查所有进程的内核栈,确保它们不在旧函数中;全部安全撤离后旧函数不再被调用。
实现原理
// kernel/livepatch/core.c + kernel/livepatch/patch.c
// 基于 ftrace:
// 1. 注册 livepatch:
→
→ // 对每个要替换的函数
→ // 设 ftrace hook
→ 函数入口被替换为 ftrace trampoline → livepatch handler → 新函数
// 2. 一致性检查 (安全迁移):
→
→ // 检查内核栈
→ 如果 task 在 old_func 中 → 不能迁移 → 等待或强制
→ 全部离开 → old_func 不再是任何进程的"当前执行点"
// 3. 完成: patch->state = KLP_PATCHED
一致性模型
// 三种模型:
// KLP_TRANSITION_IDLE: 等所有进程自愿离开 (等待点: syscall 边界)
// KLP_TRANSITION_FORCE: 发信号强制离开 (如果可能)
// KLP_TRANSITION_IMMEDIATE: 立即打补丁 (不等待, 但如果进程在旧函数中→可能 crash)
// 实际大多使用 IDLE (安全) 或信号辅助 (klp_send_signals)
限制
- 不能修改函数签名 (参数类型/数量不变)
- 不能修改数据结构布局 (patch 前后 struct 大小不能变)
- 不能打有状态的补丁 (如果旧代码持有锁 → 补丁后可能死锁)
- livepatch 模块不能卸载 (永久生效)
适合: CVE 修复, 单个函数的防御性检查
不适合: 大规模重构, 跨版本迁移
实时内核 (PREEMPT_RT)
合并状态 (6.x): PREEMPT_RT 正在被合并到主线
过去: out-of-tree patchset (rt.wiki.kernel.org)
现在: 逐个 PR 往主线合入 (6.12 接近完成)
与 livepatch 的关系:
RT 中关抢占改为 rt_mutex → livepatch 的栈检查逻辑需要适配
→ 已处理 (6.5+)
参考
- 源码:
kernel/livepatch/,samples/livepatch/,arch/x86/kernel/livepatch.c - 内核文档:
Documentation/livepatch/ - LWN: "Live patching in the Linux kernel"
关键词: livepatch, klp, ftrace, stack check, atomic replace, PREEMPT_RT, CVE fix