kpatch支持内核函数在线热更新,但仅限于满足签名一致、非static、已导出等严格约束的函数;回滚需通过预置revert补丁实现,而非简单卸载。

kpatch 能在线热更新内核函数,但**不能无条件“热更新”任意补丁**——它只允许替换满足严格约束的函数,且回滚不是卸载,而是切换到另一个预置版本。
确认内核是否支持 livepatch 并启用 CONFIG_LIVEPATCH
不满足这个前提,kpatch 加载会直接失败,报错 Operation not supported 或找不到 /sys/kernel/livepatch 目录。
- 检查内核配置:
zcat /proc/config.gz | grep CONFIG_LIVEPATCH(若未压缩则查/boot/config-$(uname -r)),必须为y - 验证运行时支持:
ls /sys/kernel/livepatch应存在;若无,说明内核虽编译了选项,但启动时被禁用(如 boot param 含livepatch.disable=1) - 某些发行版(如 RHEL 8+、Alibaba Cloud Linux 3)默认开启;Ubuntu 需手动安装
linux-image-extra或启用对应内核 flavor
构建补丁模块时 kpatch-build 报错常见原因
构建失败往往不是语法问题,而是环境或语义不匹配。最常卡在符号解析和函数状态校验环节。
-
"no symbols found for function XXX":目标函数未导出(EXPORT_SYMBOL_GPL缺失)、或不在vmlinux符号表中(如被static修饰、或编译优化移除) -
"function signature mismatch":新旧函数参数个数、类型、const修饰符不一致;即使只改一行日志,也要确保签名完全相同 -
"cannot find kernel source":kpatch-build需要与当前uname -r完全一致的内核源码 +debuginfo包;Alibaba Cloud Linux 用户需装kernel-debuginfo-$(uname -r) - 不要用
git diff直接生成 patch;必须基于原始内核源树的src.orig/和修改后目录做diff -Nupr,否则重定位失败
加载补丁后 /sys/kernel/livepatch/<patch>/enabled</patch> 一直为 0
这表示替换未生效,不是加载失败,而是被安全机制阻塞——此时内核仍在运行旧函数。
- 检查
/sys/kernel/livepatch/<patch>/status</patch>:若为checking或disabled,说明有函数正在栈上执行(如中断上下文、软中断、RCU callback 中调用该函数) - 用
ps auxf | grep "kthreadd"观察stop_machine是否卡住;高负载或实时任务密集时,安全点等待可能超时 - 临时降低干扰:停掉监控 agent、暂停大流量业务、避免触发相关子系统(如打的是 XFS 补丁,就别在此时跑
xfs_info) - 强制触发检查:
echo 1 > /sys/kernel/livepatch/<patch>/enable</patch>可重试,但不会绕过一致性校验
想“撤回”已加载的补丁,为什么 kpatch unload 失败?
kpatch unload 不是回滚操作,它只在补丁是唯一生效层、且无其他 patch 依赖它时才允许——生产环境几乎总被拒绝,报 -EBUSY。
- 真正可行的路径是:先构建并
kpatch load一个显式的 revert patch(例如把变量改回去、恢复被 hook 的回调函数指针) - 等它的
status变为applied,再kpatch unload原 patch;顺序颠倒会导致状态混乱 - 注意 revert patch 本身也受函数签名限制,不能新增逻辑;它只是“回到前一个函数版本”的镜像
- RPM 分发的热补丁(如
kernel-hotfix-xxx)通常自带配套 revert 包,命名含-revert后缀,别漏装











