1. kpatch 是什么?
livepatch 实时或动态内核修补允许为正在运行的内核提供功能增强,无需重新启动系统,这对于某些在线系统修复安全漏洞非常有帮助。
Kpatch 是给 Linux 内核 livepatch 的工具,由 Redhat 公司出品。最早出现的打热补丁工具是 Ksplice。但是 Ksplice 被 Oracle 收购后,一些发行版生产商就不得不开发自己的热补丁工具,分别是 Redhat 的 Kpatch 和 Suse 的 KGraft。同时,在这两家厂商的推进下,kernel 4.0 开始,开始集成了 livepatch 技术。 Kpatch 虽然是 Redhat 研发,但其也支持 Ubuntu、Debian、Oracle Linux 等的发行版。
livepatch 不是万能的,尤其是现在技术还不足够成熟的时候。在使用 Kpatch livepatch 存在的限制:
- 不支持修改 init 函数 (用 __init 注解) 的补丁。如果补丁试图这样做,kpatch-build 将返回一个错误。
- 不直接支持修改静态分配数据的补丁, kpatch-build 会检测到并返回错误。这个限制可以通过使用回调或影子变量来克服,如补丁作者指南中所述。
- 改变函数与动态分配数据交互方式的补丁可能是安全的,也可能不是。kpatch-build 不可能验证这种补丁的安全性。这取决于用户是否了解这个补丁的作用,新的函数与动态分配数据的交互方式是否与旧的函数不同,以及将这样的补丁原子化地应用到运行中的内核上是否安全。
- 不支持修改 vdso 函数的补丁。这些补丁在用户空间中运行,ftrace 无法钩住它们。
- 不支持修改缺少 fentry 调用的函数的补丁。这包括任何被归档到 lib.a 库中供以后链接的 lib-y 目标 (例如 lib/string.o)。
目前,kpatch 与 ftrace 和 kprobes 的使用之间存在一些不兼容的情况。更多细节请参见常见问题部分。
本文将介绍在 CentOS7.7下安装和使用 Kpatch 软件,并用于解决我们在 kubenetes 集群中由于 service 过多导致 ipvs 中 estimation_timer 函数的内核延时过高,从而导致网络都发包抖动的问题。 该问题的完整描述可以参见这里 的第二部分,我们的排查方式类似,这里我们重点讲述修复的方式。
我们生产环境中大概存在 30000 条左右的 ipvs 规则,主机命名空间中的 estimation_timer 在内核中的遍历耗时非常高,参见下图

2. kpatch 样例测试
2.1 安装
我们的平台是 CentOS 7.7.1908 版本,内核版本为 3.10.0-1062.9.1.el7.x86_64。
$ lsb_release -a
LSB Version: :core-4.1-amd64:core-4.1-noarch
Distributor ID: CentOS
Description: CentOS Linux release 7.7.1908 (Core)
Release: 7.7.1908
Codename: Core
$ uname -a
Linux 3.10.0-1062.9.1.el7.x86_64 #1 SMP Fri Dec 6 15:49:49 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux
# 检查一下我们系统是否已经支持了 live patch
$ cat /boot/config-3.10.0-1062.9.1.el7.x86_64 |grep PATCH
CONFIG_HAVE_LIVEPATCH=y
CONFIG_LIVEPATCH=y
CONFIG_DVB_BUDGET_PATCH=m
CONFIG_SND_HDA_PATCH_LOADER=y
安装官方仓库给的安装文档中关于 Fedora, RHEL, CentOS 中的章节:
# 从官方拉取仓库
$ git clone https://github.com/dynup/kpatch.git
$ source test/integration/lib.sh
# 中间会使用 yum 安装相关的依赖包,安装时间视网络情况而定,在阿里云的环境下需要的时间比较长
$ sudo kpatch_dependencies
$ cd kpatch
# 进行编译
$ make
# 默认安装到 /usr/local,需要注意 kpatch-build 在目录 /usr/local/bin/ 下,而 kpatch 在 /usr/local/sbin/ 目录
$ sudo make install
$ /usr/local/bin/kpatch-build -h
usage: kpatch-build [options] <patch1 ... patchN>
patchN Input patchfile(s)
-h, --help Show this help message
-a, --archversion Specify the kernel arch version
-r, --sourcerpm Specify kernel source RPM
-s, --sourcedir Specify kernel source directory
-c, --config Specify kernel config file
-v, --vmlinux Specify original vmlinux
-j, --jobs Specify the number of make jobs
-t, --target Specify custom kernel build targets
-n, --name Specify the name of the kpatch module
-o, --output Specify output folder
-d, --debug Enable 'xtrace' and keep scratch files
in <CACHEDIR>/tmp
(can be specified multiple times)
-e, --oot-module Enable patching out-of-tree module,
specify current version of module
--skip-cleanup Skip post-build cleanup
--skip-gcc-check Skip gcc version matching check
(not recommended)
到此 kpatch 已经安装到了系统中。舞台已经搭建完成,但是我们还需要演员登场,而演员就是我们系统运行的内核源码。
在安装过程中已经安装了内核的对应的 debug 包,内核的源码位于以下目录:
/usr/src/debug/kernel-3.10.0-1062.9.1.el7/linux-3.10.0-1062.9.1.el7.x86_64
2.2 官方样例测试
我们使用官方提供的样例程序进行简单测试:
$ cd kpatch/test/integration/rhel-7.7
$ cat meminfo-string.patch
Index: kernel/fs/proc/meminfo.c
===================================================================
--- kernel.orig/fs/proc/meminfo.c
+++ kernel/fs/proc/meminfo.c
@@ -99,7 +99,7 @@ static int meminfo_proc_show(struct seq_
"Committed_AS: %8lu kB\n"
"VmallocTotal: %8lu kB\n"
"VmallocUsed: %8lu kB\n"
- "VmallocChunk: %8lu kB\n"
+ "VMALLOCCHUNK: %8lu kB\n"
#ifdef CONFIG_MEMORY_FAILURE
"HardwareCorrupted: %5lu kB\n"
#endif
$sudo /usr/local/bin/kpatch-build -t vmlinux meminfo-string.patch
ERROR: gcc/kernel version mismatch
gcc version: GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-44)
kernel version: GCC: (GNU) 4.8.5 20150623 (Red Hat 4.8.5-39)
Install the matching gcc version (recommended) or use --skip-gcc-check
to skip the version matching enforcement (not recommended)
ERROR: kpatch build failed.
# 这个报错

本文详细介绍Kpatch工具的安装与使用,通过实战案例演示如何解决内核中的estimation_timer函数引起的网络延迟问题。文章涵盖Kpatch的基本概念、安装步骤、限制条件及如何针对特定问题制作并应用热补丁。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



