如果内核有bug需要修复, 一般的流程是把内核升级到问题修复的版本, 但升级内核需要重启机器, 这样如果线上服务的机器就需要先停服在升级内核再重启机器重启服务, 会影响服务且升级周期太长, 所以应对一些小修复我们可以利用livepatch 热补丁的方式修复, 可以做到不停服不停机来修复问题, 且修复周期小成本低。
-
在centos自带内核上打热补丁使用示例
- 下载源码编译
- git clone https://github.com/dynup/kpatch.git
- make
- 安装相应rpm
- kernel-3.10.0-957.21.3.el7.x86_64.rpm
- kernel-debuginfo-3.10.0-957.21.3.el7.x86_64.rpm
- kernel-debuginfo-common-x86_64-3.10.0-957.21.3.el7.x86_64.rpm
- kernel-devel-3.10.0-957.21.3.el7.x86_64.rpm
- 解压kernel-3.10.0-957.21.3.el7.x86_64.src.rpm
- rpm –ivh kernel-3.10.0-957.21.3.el7.x86_64.src.rpm 执行rpm安装命令
- cd /root/rpmbuild/SPECS 切换目录到/root/rpmbuild/SPECS
- rpmbuild –bp kernel.spec 执行rpmbuild会生成源码包
- /root/rpmbuild/BUILD/kernel-3.10.0-957.21.3.el7 这就是源码包
- 在上面解压出来的源码上生成要修复的patch
- 切换gcc版本, gcc版本最好和编译内核的版本一致, 但比较难做到一致, 如果不一致需要用--skip-gcc-check这个选项, gcc用高版本
- source /opt/rh/devtoolset-7/enable
- 使用kpatch-build编译出livepatch
- /kpatch-build/kpatch-build -v /usr/lib/debug/lib/modules/3.10.0-957.21.3.el7.x86_64/vmlinux -s /root/rpmbuild/BUILD/kernel-3.10.0-957.21.3.el7 /tmp/0001-kpatch-test.patch --skip-gcc-check
- 最终会生成livepatch-0001-kpatch-test.ko这个模块
- kpatch 使用
- 打patch
- kpatch load livepatch-0001-kpatch-test.ko
- 或者直接insmod livepatch-0001-kpatch-test.ko
- 卸载patch
- kpatch unload livepatch-0001-kpatch-test.ko
- 打patch
- 下载源码编译
-
livepatch一些问题
- livepatch资料
- https://www.kernel.org/doc/html/latest/livepatch/livepatch.html
- 基本原理是livepatch是利用ftrace在函数开头跳转到新的函数
- 局限性
- 不支持数据结构的修改, 不支持修改静态数据参数, 只支持函数修改
- 只支持可以被ftrace的函数
- 如果一个函数已经被ftrace过, 例如被kprobe hook过, 那么就不能打livepatch
- 问题
- kpatch打不上
- kpatch load --all 运行后出错, 提示transition stalled
- 打开livepatch的相关debug log
- sudo sh -c 'echo "file kernel/livepatch/transition.c -p" > /sys/kernel/debug/dynamic_debug/control'
- 出现很多`livepatch: klp_try_switch_task: swapper/78:0 is running`的log
- 内核社区发现相关的问题修复
- 两个livepatch只有一个生效
- 发现是kpatch-build 编译出的livepatch的replace属性是开的, 编译时加-R可以关闭
- kpatch打不上
- livepatch资料