linux 热补丁机制基本概念

本文介绍了Linuxlivepatch技术,一种无需重启内核即可动态应用补丁到内核的机制,主要依赖kprobe和ftrace。文章详细讨论了patch的安全注入方法,包括使用可靠的堆栈跟踪和在特定上下文中进行修补。文章还概述了活体补丁的实现原理,以及其在不同架构下的限制和使用示例。

linux 热补丁技术叫 livepatch 机制,可以在不重启内核的情况下应用补丁到内核中,常用于服务器环境,比如服务器处于生产环境不能随意重启,而为了应对某些临时发现漏洞修补,则可以通过该机制进行动态修复。

  • 依赖于 kprobe 和 ftrace 机制来实现 patch 注入。
  • 需要一致性模型

一致性模型:
一般 patch 修复不会改变一个函数的语义,只是为了添加一个 null 指针或者边界检查,添加一些内存屏障,或者给临界区加锁。还有一些复杂的 patch 会修改锁的顺序,修改变量,更新函数功能。所以需要一个一致性模型来解决这些问题。

kpatch 有下面的方式跟踪注入 patch 是安全的:

  • 第一种最有效方式:对睡眠任务进行堆栈检查,如果任务的堆栈上没有需要修改的函数,那么则是可以进行安全修复。大多数情况下,会在这时完成修补,否则周期性尝试检查并修补。这个能力需要 arch 提供 HAVE_RELIABLE_STACKTRACE 可靠栈支持。(目前仅 powerpc 和 x86 提供了该支持)
  • 第二种是内核从系统调用,用户空间 irq 和 信号返回到用户空间时,任务被切换,此时在以下两种情况有效:(1)修补是在受影响的函数上休眠的 i/o 绑定任务,这种可以通过 SIGSTOP 和 SIGCNT 信号强制退出后来进行补丁修补(2)修补是 cpu 绑定任务。如果任务是高度 cpu 绑定的,那么它将在下一次被 irq 中断时得以修补。
  • “swapper“ 任务,在进入 idle 前调用 klp_update_patch_state() ,此时可以进行修补。

如果 arch 没有 HAVE_RELIABLE_STACKTRACE 支持,则只能使用第二种修补方式。但无论怎样不支持 HAVE_RELIABLE_STACKTRACE 都会被认为是不完全受支持的 livepatch。

实现原理简述:

ftrace 原理详细分析这篇文章中 中知道:每个 tracer 实现 struct ftrace_ops 来在指定的 hook 点调用回调函数。livepatch 利用了这个 ftrace_ops,在 hook 点调用回调并调用相对应 patch 中的函数,并修改返回地址,实现一个函数的修补功能。

该过程可以分为load,enable,replace,disable,removing 五个步骤,其中 load 负责加载补丁,enable 负责注册 ftrace 等操作,replace 在合适时机调用 stop_machine 替换函数。

可以看到 livepatch 的修补单位是函数,其中对 patch 具有许多限制:

  • 只有可以被 trace 的函数才能被修补
    livepatch 需要动态 ftrace 支持,相对应的 notrace 的函数不能被修补,否则可能导致代码陷入无限循环。
  • 需要动态 ftrace 位于函数的最开始,也就是架构支持 -mfentry 编译选项(可以看 ftrace 原理详细分析 中的介绍),目前 x86 支持,arm64 不支持。
  • kretporbe 和 livepatch 是冲突的,因为他们实现都是基于在 hook 点修改返回值实现的,具体还是可以看 kprobe 原理详细分析 中对 kprobe 原理分析。

限制:
一些编写 patch 上的限制:
(1)补丁之间的交互
补丁之间可能存在潜在交互,所以建议补丁是以累计升级模式制作,即第二个补丁基于第一个补丁制作,并且第二个补丁是第一个补丁的累积升级。
(2)数据结构的修改
kpatch 修补的单位是函数,而不是数据结构,如果补丁对数据结构进行了修改,那一般会出问题,需要重新制作补丁,默认不允许修改数据结构,如果这样做了,kpatch-build 可能会抛出错误。
如果实在需要对数据结构中变量修改,可以使用 livepatch 提供的影子变量机制来分配一个变量使用。
(3)不能修补 __init 的函数
它们只会被调用一次,且可能涉及硬件初始化条件。
(4)头文件修改
头文件修改可能导致大范围数据产生变化,破坏数据结构。
(5)小心意外更改的函数
如内联函数,新补丁中的函数可能被编译器内联。
(6)静态局部变量
静态局部变量是全局变量,patch 中无法默认对其修改。
(7)移除代码
patch 中不要移除老的修复代码,只能新增代码,被移除的代码在 kpatch-build 作用下会被保留。
(8)禁止对 once 相关宏使用
类似的 pintk_once。。。等等会将变量存储在 __data_once 中,这是静态的,我们不能再去修改。

还有其他一些限制:可以参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值