22 使用 kGraft 在线增补 Linux 内核 #
本文档介绍 kGraft 在线增补技术的基本原理,并提供 SLE Live Patching 服务的使用准则。
kGraft 是一项在线增补技术,使用它可在运行时增补 Linux 内核,而无需停止内核。如此可以最大程度地确保系统运行时间,从而提高系统可用性,这对于任务关键型系统而言非常重要。该技术还允许动态增补内核,支持用户安装关键的安全性更新,不必将它们推迟到安排的停机时间。
kGraft 增补程序是一个内核模块,用于替换内核中的全部函数。kGraft 主要提供内核中基础结构,可在运行时将增补的代码与基本内核代码集成。
SLE Live Patching 是在常规 SUSE Linux Enterprise Server 维护基础之上提供的服务。通过 SLE Live Patching 分发的 kGraft 是对常规 SLES 维护更新的有益补充。可以使用常用的更新堆栈和过程来部署 SLE Live Patching。
本文档中提供的信息与 AMD64/Intel 64 和 POWER 体系结构相关。如果您使用的不是这些体系结构,则相关的过程可能有所不同。
22.1 kGraft 的优势 #
当需要对紧急情况(已知发生了应该尽力修复的严重漏洞,或者已知的修复程序出现严重的系统稳定性问题)迅速做出响应时,使用 kGraft 进行在线内核增补特别有用。该技术不适合用于非时间关键型的已安排更新。
kGraft 的典型用例包括:配有巨量 RAM,且引导时间经常长达 15 分钟或以上的内存数据库之类的系统、需要持续数周或数月不重启动的大规模仿真,或者向众多消费者持续提供服务的基础架构构建模块。
kGraft 的主要优势是它永不要求停止内核,哪怕是短暂停止。
kGraft 增补程序是 RPM 包中的一个 .ko
内核模块。可以在安装或更新 包时,使用 insmod
命令将它插入内核。kGraft 将替换内核中的全部函数,即使这些函数正在执行。如果需要,可以使用更新的 kGraft 模块替换现有增补程序。
kGraft 也很精简 - 因为利用了其他标准 Linux 技术,它只包含少量的代码。
22.2 kGraft 的底层函数 #
kGraft 使用 ftrace 基础结构执行增补。下面介绍了在 AMD64/Intel 64 体系结构上的实施过程。
为了增补某个内核函数,kGraft 要求该函数的开头有一定的空间,以便插入指向新函数的跳跃点。此空间是在开启函数分析的情况下,在内核编译期间由 GCC 分配的。具体而言,将在内核函数的开头注入一个 5 字节调用指令。引导此类经过检测的内核时,分析调用将替换为 5 字节 NOP(无操作)指令。
增补开始之后,第一个字节将替换为 INT3(断点)指令。这可以确保 5 字节指令替换的原子性。其他四个字节将替换为新函数的地址。最后,第一个字节将替换为 JMP(长跳跃)操作代码。
在整个过程中,将使用处理器间不可屏蔽中断 (IPI NMI) 来刷新系统中其他 CPU 的推理解码队列。这样,无需停止内核(哪怕是非常短暂的停止),就能切换到新的函数。IPI NMI 产生的中断可用毫秒为单位测量,并且不被视为服务中断,因为无论在哪种情况下,这些中断都是在内核运行时发生的。
永远不会增补调用方。相反,调用者的 NOP 将替换为指向新函数的 JMP。JMP 指令会永久保留。这种工作方式可以处理好函数指针(包括结构中的指针),并且不需要保存任何旧数据就能取消增补。
但是,这些步骤本身并不足够完善:因为函数将以非原子方式替换,内核某个部分中新修复的函数可能仍会调用其他位置的某个旧函数,反之亦然。如果函数接口的语义在增补程序中发生更改,将会造成混乱。
因此,在替换所有函数之前,kGraft 使用基于弹簧床、类似于 RCU(读取-复制-更新)的方案,来确保每个用户空间线程、内核线程和内核中断在全局视图中都保持一致。将对每个内核入口和出口设置一个基于线程的标志。这样,一个旧函数始终会调用另一个旧函数,而一个新函数始终会调用另一个新函数。为所有进程设置“new universe”标志后,增补即告完成,此时,可以去除弹簧床函数,代码可以全速运行,且不会对性能产生影响,不过,每个增补的函数需要经历超长时间的跳转。
22.3 安装 kGraft 增补程序 #
本节介绍如何激活 SUSE Linux Enterprise Live Patching 扩展以及如何安装 kGraft 增补程序。
22.3.1 激活 SLE Live Patching #
要在您的系统上激活 SLE Live Patching,请遵循以下步骤:
如果您的 SLES 系统尚未注册,现在请注册。可以在安装系统期间完成注册,或者以后使用 YaST
模块 (yast2 registration
) 执行注册。注册后,单击 查看可用联机更新的列表。如果您的 SLES 系统已注册,但 SLE Live Patching 尚未激活,请打开 YaST
模块 (yast2 registration
),然后单击 。在可用扩展列表中选择
,然后单击 。确认许可条款并单击
。输入 SLE Live Patching 注册代码并单击
。检查
和选定的 。应该选择安装Live Patching
模式。单击
完成安装。这样就会在您的系统上安装 kGraft 基本组件以及初始在线增补程序。
22.3.2 更新系统 #
SLE Live Patching 更新通过允许使用标准 SLE 更新堆栈来应用增补程序的形式分发。可以使用
zypper patch
、YaST 联机更新或等效的方法来更新初始在线增补程序。内核将在安装包的过程中自动增补。但是,在所有休眠进程都唤醒并避开前,旧内核函数的调用并不会完全消除。这可以节省大量的时间。尽管如此,使用旧内核函数的休眠进程并不被视为安全问题。不过,在最新的 kGraft 版本中,只有当所有进程都超出了内核用户空间界限时,才可以应用另一个 kGraft 增补程序来停止使用前一增补程序已增补的功能。
要查看全局增补状态,请检查
/sys/kernel/kgraft/in_progress
中的标志。值1
表示存在仍需唤醒的休眠进程(增补仍在进行)。值0
表示所有进程都只使用了增补的函数,并且增补已经完成。或者,可以使用kgr status
命令获取相同的信息。也可以基于每个进程检查标志。针对每个进程单独检查
/proc/PROCESS_NUMBER/kgr_in_progress
中的数字。同样,值1
表示仍需唤醒的休眠进程。或者,可以使用kgr blocking
命令输出休眠进程的列表。
22.4 增补程序生命周期 #
可以使用 zypper lifecycle
来查看在线增补程序的失效日期。确保包
lifecycle-data-sle-live-patching 已安装。
tux >
zypper lifecycle
Product end of support Codestream: SUSE Linux Enterprise Server 12 2024-10-31 SUSE Linux Enterprise Server 12 SP2 n/a* Extension end of support SUSE Linux Enterprise Live Patching 2017-10-31 Package end of support if different from product: SUSEConnect Now, installed 0.2.41-18.1, update available 0.2.42-19.3.1 apache2-utils Now *) See https://www.suse.com/lifecycle for latest information
当到了增补程序的失效日期时,将不再提供此内核版本的更多在线增补程序。请计划于在线增补程序生命周期结束前更新内核。
22.5 去除 kGraft 增补程序 #
要去除 kGraft 增补程序,请执行以下过程:
首先,使用 Zypper 去除增补程序本身:
zypper rm kgraft-patch-3_12_32-25-default
然后重引导计算机。
22.6 阻塞的内核执行线程 #
需要准备好内核线程才能处理 kGraft。第三方软件不一定能够配合 kGraft,并且其内核模块可能会衍生大量的内核执行线程。这些线程会无限期阻止增补过程。作为应急措施,kGraft 允许强行完成增补过程,而不等待所有执行线程跨越安全检查点。这可以通过在 /sys/kernel/kgraft/in_progress
中写入 0
来实现。在执行此过程之前,请先咨询 SUSE 支持人员。
22.7 kgr
工具 #
使用 kgr
工具可以简化一些 kGraft 管理任务。可用的命令为:
kgr status
显示 kGraft 增补的总体状态(
ready
或in_progress
)。kgr patches
显示已装载 kGraft 增补程序的列表。
kgr blocking
列出阻止 kGraft 完成增补的进程。默认情况下,只会列出 PID。指定
-v
会列显命令行(如果有)。再指定一个-v
还会显示堆栈跟踪。
有关详细信息,请参见 man kgr
。
22.8 kGraft 技术的应用范围 #
kGraft 的工作原理以替换函数为基础。数据结构的改动只能通过 kGraft 间接完成。因此,更改内核数据结构时需要特别小心,如果更改幅度太大,可能需要重引导。此外,kGraft 可能无法处理使用一个编译器来编译旧内核,使用另一个编译器来编译增补程序的情况。
由于 kGraft 的工作方式,对衍生大量内核线程的第三方模块的支持有限。
22.9 SLE Live Patching 的应用范围 #
SLE Live Patching 的应用范围包括 SUSE 通用漏洞评分系统 (CVSS) 级别 7 以上漏洞的修复,以及与系统稳定性或数据损坏相关的 Bug 修复。可能无法针对满足上述所有准则的所有修复类型生成在线增补程序。如果出于技术原因而无法生成内核在线增补程序,SUSE 有权不发布修复。有关作为 SUSE CVSS 评级基础的 CVSS 3.0 的详细信息,请参见 https://www.first.org/cvss/。
22.10 使用支持流程与我们交互 #
在与 SUSE 支持人员共同解决技术难题时,您可能会收到一个所谓的程序临时修复 (PTF)。我们可能会针对各种包(包括构成 SLE Live Patching 基础的包)发布 PTF。
您可以像平时一样安装符合上一节中所述条件的 kGraft PTF,SUSE 将确保无需重引导有问题的系统,并且将来的在线更新可以正常应用。
针对基础内核发布的 PTF 会中断在线增补过程。首先,安装 PTF 内核意味着需要重引导,因为在运行时无法替换整个内核。其次,需要再次重引导,以便将 PTF 替换为对其发布了在线增补程序的任何常规维护更新。
可将 SLE Live Patching 中其他包的 PTF 视为享有正常担保的常规 PTF。