8 使用 KLP 的在线内核增补 #
本文档介绍内核在线增补 (KLP) 技术的基本原理,并提供 SLE Live Patching 服务的使用准则。
KLP 是一项在线增补技术,使用它可在运行时增补 Linux 内核,而无需停止内核。如此可以最大程度地确保系统运行时间,从而提高系统可用性,这对于任务关键型系统而言非常重要。该技术还允许动态增补内核,支持用户安装关键的安全性更新,而不必将它们推迟到安排的停机时间。
启用 KLP 无需执行特殊步骤,只需启用 Live Patching 服务,然后应用可用的增补程序即可。该服务是常规软件管理系统的一部分,使用常用包管理工具安装(或去除)增补程序。无需安装或手动选择特殊内核。
KLP 增补程序是一个内核模块,用于替换内核中的全部函数。内核在线增补主要提供内核中基础结构,可在运行时将增补的代码与基本内核代码集成。
本文档中提供的信息与 AMD64/Intel 64 和 POWER 体系结构相关。Xen 超级管理程序支持 KLP。
8.1 内核在线增补的优势 #
当发现应该尽快修复的严重漏洞或系统稳定性问题时,使用 KLP 的内核在线增补能够快速做出紧急响应。该技术不适合用于非时间关键型的已安排更新。
内核在线增补的典型用例包括:配有巨量 RAM 且引导时间通常长达 15 分钟或以上的内存数据库之类的系统、需要持续数周或数月不重启动的大规模仿真,或是向众多客户持续提供服务的基础结构构建块组。
内核在线增补的主要优势是它永不要求停止内核,哪怕是短暂停止。
KLP 增补程序是 RPM 包中的一个 .ko
内核模块。可以在安装或更新 包时,使用 insmod
命令将它插入内核。内核在线增补将替换内核中的全部函数,即使这些函数正在执行。如果需要,可以使用更新的 KLP 模块替换现有增补程序。
此外,内核在线增补非常精简 - 因为利用了其他标准 Linux 技术,它只包含少量的代码。
8.2 内核在线增补的低级函数 #
内核在线增补使用 ftrace 基础结构执行增补。下面介绍了在 AMD64/Intel 64 体系结构上的实施过程。
为了增补某个内核函数,内核在线增补要求该函数的开头有一定的空间,以便插入指向新函数的跳跃点。此空间是在开启函数分析的情况下,在内核编译期间由 GCC 分配的。具体而言,将在内核函数的开头注入一个 5 字节调用指令。引导此类经过检测的内核时,分析调用将替换为 5 字节 NOP(无操作)指令。
增补开始之后,第一个字节将替换为 INT3(断点)指令。这可以确保 5 字节指令替换的原子性。其他四个字节将替换为新函数的地址。最后,第一个字节将替换为 JMP(长跳跃)操作代码。
在整个过程中,将使用处理器间不可屏蔽中断 (IPI NMI) 来刷新系统中其他 CPU 的推理解码队列。这样,无需停止内核(哪怕是非常短暂的停止),就能切换到新的函数。IPI NMI 产生的中断可用毫秒为单位测量,并且不被视为服务中断,因为无论在哪种情况下,这些中断都是在内核运行时发生的。
永远不会增补调用方。被调用方的 NOP 将替换为指向新函数的 JMP。JMP 指令会永久保留。这种工作方式可以处理好函数指针(包括结构中的指针),并且不需要保存任何旧数据就能取消增补。
但是,这些步骤本身并不足够完善:因为函数将以非原子方式替换,内核某个部分中新修复的函数可能仍会调用其他位置的某个旧函数,反之亦然。如果函数接口的语义在增补程序中发生更改,将会造成混乱。
因此,在替换所有函数之前,内核在线增补使用基于弹性机制且类似于 RCU(读取-复制-更新)的方案,来确保每个用户空间线程、内核线程和内核中断在全局视图中都保持一致。将对每个内核入口和出口设置一个基于线程的标志。这样,一个旧函数始终会调用另一个旧函数,而一个新函数始终会调用另一个新函数。为所有进程设置“new universe”标志后,增补即告完成,此时,可以去除弹簧床函数,代码可以全速运行,且不会对性能产生影响,不过,每个增补的函数需要经历超长时间的跳转。
8.3 激活 SLE Live Patching #
要在您的系统上激活 SLE Live Patching,请遵循以下步骤:
您的 SLES 系统必须已注册。可以在系统安装期间注册该系统,也可以在安装后使用 YaST
模块 (yast2 registration
) 注册该系统。如果您的 SLES 系统已注册,但 SLE Live Patching 尚未激活,请运行yast2 registration
命令,然后单击 。在可用扩展列表中选择
,然后单击 。确认许可条款并单击
。输入您的 SLE Live Patching 注册代码并单击
。检查
和选定的 。系统会为安装自动选择模式Live Patching
和SLE Live Patching Lifecycle Data
,同时为满足依赖性可能还会选择安装一些其他包。单击
完成安装。也就是说,会在您的系统上安装基础内核在线增补组件、初始在线增补程序,以及任何依赖包。
8.4 安装和去除增补程序 #
本节介绍如何查找、安装和去除 KLP 增补程序。
8.4.1 安装 KLP 增补程序 #
在安装新的增补程序之前,请运行
klp status
命令查询当前状态,该状态必须是ready
而不能是in_progress
。只有在完成前面的增补程序安装之后,才能应用新的增补程序。在唤醒并去除所有休眠进程前,都无法完全消除旧内核函数的调用。这可以节省大量的时间。但我们并不认为使用旧内核函数的休眠进程存在安全问题。(有关如何管理长时间in_progress
状态的信息,请参见第 8.6 节 “阻塞的内核执行线程”。)使用常规包管理系统
zypper
或 YaST 查看和安装可用的增补程序。以下示例将搜索可用的增补程序,然后安装最新的增补程序。不需要按顺序逐一安装所有增补程序;存在多个可用的增补程序时,只需要安装最新的增补程序。tux >
sudo
zypper se kernel-livepatch | kernel-livepatch-5_3_18-8_16-default | Kernel live patch module | package | kernel-livepatch-5_3_18-8_19-default | Kernel live patch module | package | kernel-livepatch-5_3_18-8_22-default | Kernel live patch module | packagetux >
sudo
zypper in kernel-livepatch-5_3_18-8_22-default
8.4.2 去除 KLP 增补程序 #
如果您需要去除某个 KLP 增补程序,请使用 zypper
,就像去除任何其他包一样。使用 zypper
搜索 kernel-livepatch
,列出已安装的在线增补程序包:
tux >
sudo
zypper se -kernel-livepatch | kernel-livepatch-5_3_18-8_16-default | Kernel live patch module | package | kernel-livepatch-5_3_18-8_19-default | Kernel live patch module | package i | kernel-livepatch-5_3_18-8_22-default | Kernel live patch module | package
使用
zypper
去除增补程序:tux >
sudo
zypper rm kernel-livepatch-5_3_18-8_22-default等待
initrd
自动重构建,然后重引导计算机。
8.5 klp
工具 #
使用 klp
工具可以简化一些内核在线增补管理任务。可用的命令为:
klp status
显示内核在线增补的总体状态(
ready
或in_progress
)。klp patches
显示已装载 KLP 增补程序的列表。
klp blocking
列出阻止完成内核在线增补的进程。默认情况下,只会列出 PID。指定
-v
会列显命令行(如果有)。-vv
显示堆栈跟踪。
有关详细信息,请参见 man klp
。
8.6 阻塞的内核执行线程 #
内核线程必须已准备好处理内核在线增补。第三方软件可能不支持内核在线增补,并可能会衍生内核执行线程。这些线程会无限期阻止增补过程。作为紧急应对措施,可以通过将 0
写入 /sys/kernel/livepatch/*/transition/
(请将星号通配符替换为您的文件名),来强制完成增补进程,而不必等到所有执行线程都通过安全检查点。在执行此过程之前,请先咨询 SUSE 支持人员。
8.7 增补程序生命周期 #
可以使用 zypper lifecycle
来查看在线增补程序的失效日期。(确保包
lifecycle-data-sle-module-live-patching 已安装。)
当到了增补程序的失效日期时,将不再提供此内核版本的更多在线增补程序。请在在线增补程序生命周期期限结束之前规划内核更新。
有关 zypper lifecycle
的细节,请参见《管理员指南》中的“显示生命周期信息”。
8.8 内核在线增补技术的范围 #
内核在线增补基于函数替换。数据结构的改动只能通过内核在线增补间接完成。因此,更改内核数据结构时需要特别小心,如果更改幅度太大,可能需要重引导。此外,对于使用一个编译器来编译旧内核而使用另一个编译器来编译增补程序的情况,内核在线增补可能无法处理。
由于内核在线增补的工作方式,对衍生大量内核线程的第三方模块的支持有限。
8.9 SLE Live Patching 的应用范围 #
SLE Live Patching 的应用范围包括 SUSE 通用漏洞评分系统(CVSS;SUSE CVSS 基于 CVSS v3.0 系统)级别 7 以上漏洞的修复,以及与系统稳定性或数据损坏相关的 Bug 修复。可能无法针对满足上述所有准则的所有修复类型生成在线增补程序。如果出于技术原因而无法生成内核在线增补程序,SUSE 有权不发布修复。有关作为 SUSE CVSS 评级基础的 CVSS 的详细信息,请参见 https://www.first.org/cvss/。
8.10 使用支持流程与我们交互 #
在与 SUSE 支持人员共同解决技术难题时,您可能会收到一个程序临时修复 (PTF)。我们可能会针对各种包(包括构成 SLE Live Patching 基础的包)发布 PTF。
您可以像平时一样安装符合上一节中所述条件的内核在线增补 PTF,SUSE 将确保无需重引导有问题的系统,并且将来的在线更新可以正常应用。
针对基础内核发布的 PTF 会中断在线增补过程。首先,安装 PTF 内核意味着需要重引导,因为在运行时无法替换整个内核。其次,需要再次重引导,以便将 PTF 替换为对其发布了在线增补程序的任何常规维护更新。
可将 SLE Live Patching 中其他包的 PTF 视为享有正常担保的常规 PTF。