能否无需重启修复内核,取决于内核是否启用config_livepatch=y或config_kpatch=y等热补丁支持选项,而非仅安装工具;主流发行版在满足内核配置和依赖(如ftrace、kallsyms)前提下可开箱即用。

kpatch 和 livepatch 是当前 Linux 系统中实现内核热补丁的两个主流方案,但它们的配置路径、依赖条件和适用范围差异很大。是否能“无需重启修复内核”,不取决于你装了什么工具,而取决于你的内核是否启用并支持运行时函数替换机制。
结论很直接:
如果你用的是主流发行版(RHEL/CentOS 7+/8+/9、Ubuntu 16.04+/18.04+/20.04+、SLES 12+/15+),且内核已开启 CONFIG_LIVEPATCH=y 或 CONFIG_KPATCH=y,那么热补丁可开箱即用;否则,哪怕装了 kpatch-build,也编译不出可用模块。
确认内核是否支持 livepatching
不是所有内核都默认开启热补丁能力。必须检查内核编译配置:
- 运行
zcat /proc/config.gz | grep CONFIG_LIVEPATCH(若提示无此文件,尝试grep CONFIG_LIVEPATCH /boot/config-$(uname -r)) - 预期输出应为
CONFIG_LIVEPATCH=y或CONFIG_KPATCH=y;若为=m,说明需手动加载模块(部分发行版会禁用) - 若输出为空或
=n,代表该内核不支持——此时安装kpatch工具链也没用,必须换内核或重编译 - RHEL/CentOS 用户可直接查
uname -r是否含kernel-livepatch字样;Ubuntu 用户可运行canonical-livepatch status
注意:CONFIG_FTRACE、CONFIG_FUNCTION_TRACER、CONFIG_KALLSYMS 也必须为 y,否则 livepatch 无法定位和跳转函数入口。
使用 canonical-livepatch(Ubuntu 专属)
Ubuntu 提供开箱即用的托管式热补丁服务,无需自己编译补丁,但仅覆盖 Canonical 官方发布的 CVE 修复:
- 先注册获取 token:
sudo canonical-livepatch enable YOUR_TOKEN(token 来自 https://auth.livepatch.canonical.com/) - 启用后自动轮询更新,补丁通常在几秒内加载完成
- 验证状态:
canonical-livepatch status --verbose,关注KernelStatus是否为apply-error或applied - 常见失败原因:内核版本不在支持列表(如自编译内核、非 HWE 内核)、
/var/lib/ubuntu-livepatch权限异常、systemd-timers 被禁用
该方式不提供自定义补丁能力,也不支持第三方驱动或模块热更新。
手动构建并加载 kpatch 补丁模块
适用于需要修复私有内核模块、定制补丁或 RHEL/CentOS 场景。核心难点不在命令本身,而在补丁源码与目标内核的 ABI 兼容性:
- 确保已安装
kpatch-build(RHEL/CentOS:来自rhel-8-for-x86_64-appstream-rpms;Ubuntu:需从源码编译) - 准备原始内核源码树(必须与
uname -r完全一致,包括~1、+debug等后缀) - 补丁文件
fix.patch必须只修改单个函数,且不能改动函数签名、调用约定、栈帧布局;kpatch-build会拒绝含结构体变更、全局变量增删的 patch - 构建命令:
kpatch-build -s /path/to/vanilla/kernel/src/ fix.patch;成功后生成fix.ko - 加载:
sudo kpatch load fix.ko;失败时看dmesg | tail -20,典型错误如"failed to find symbol __fentry__"(ftrace 未启用)、"inconsistent state"(已有其他 livepatch 加载)
关键限制:kpatch 不支持递归调用修复、不支持中断上下文中的函数替换、不支持 inline 函数——这些在构建阶段不会报错,但加载后可能引发 panic。
livepatch 模块加载后为何没生效?
补丁加载成功 ≠ 功能修复成功。很多用户卡在这一步,误以为“kpatch load 返回 0 就万事大吉”:
- 检查
/sys/kernel/livepatch/下是否有对应目录,其enabled文件值是否为1 - 确认目标函数确实被调用过:比如修复的是
ext4_write_begin,需触发一次文件写入才能激活跳转 -
livepatch是惰性替换——只有当函数首次被调用时,才通过 ftrace handler 重定向到新实现;此前所有调用仍走旧路径 - 若函数正在被其他模块(如
kprobe、perf)探测,livepatch可能拒绝加载或静默失效(见内核文档Documentation/livepatch/livepatch.txt中 “Limitations” 章节)
最易被忽略的一点:热补丁只作用于函数级别,对宏定义、头文件常量、内联汇编、initcall 顺序等完全无效——这类问题仍需冷升级。











