kpatch/README.md
HuBin95 5df73ddec7
update README doc
Signed-off-by: HuBin95 <hubin73@huawei.com>
2023-08-01 07:20:16 +00:00

245 lines
6.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

openEuler内核热补丁使用指南
----------
支持操作系统:
openEuler 20.03 LTS及以上版本
openEuler社区已经验证支持内核热补丁的架构
- [x] x86_64
- [x] arm64
- [ ] ppc64le
- [ ] s390
- [ ] risc-v
上游社区:
https://github.com/dynup/kpatch
## 内核热补丁说明
内核热补丁一般用于在不重启机器的前提下在线修复内核函数问题。
常用场景:
- 在线修复内核漏洞(CVE、bugfix)
- 在线修复驱动漏洞(bugfix)
- 内核问题定位
- 开发调试
<b>注1</b>:内核热补丁加载激活之后,若机器重启,则热补丁失效,需重新加载激活才能继续生效。
若需要机器重启后自动加载激活热补丁,可编写启动执行脚本,在脚本里加载激活指定的热补丁。
<b>注2</b>:热补丁存在一定的<b><i>约束限制</i></b>,部分场景下无法做补丁,详见最后一节。
## 环境准备
安装依赖软件包
```bash
yum install -y make gcc patch bison flex openssl-devel kpatch kpatch-runtime elfutils-libelf-devel
```
安装当前内核源码和开发包
```bash
yum install -y kernel-source-`uname -r` kernel-debuginfo-`uname -r` kernel-devel-`uname -r`
```
进入热补丁制作目录并准备环境
```bash
cd /opt/patch_workspace
rm -rf kernel-source .config
ln -s /usr/src/linux-`uname -r`/ kernel-source
ln -s /usr/src/linux-`uname -r`/.config .config
ln -s /usr/lib/debug/lib/modules/`uname -r`/vmlinux vmlinux
```
## 制作内核热补丁
支持两种方式制作内核热补丁
### 方法1直接修改源代码的方式
进入内核源码目录(下面以修改fs/proc/cmdline.c文件为例)
```bash
cd kernel-source
cd fs/proc/
cp cmdline.c cmdline.c.new
```
此处cp操作的后缀.new在后面执行make_hotpatch时会用到
修改cmdline.c.new中的函数
开始制作热补丁
```bash
cd /opt/patch_workspace/
./make_hotpatch -d .new -i cmdline
```
参数 | 说明|
--------- | --------|
-d |前面cp操作时的唯一后缀名|
-i |补丁ID可包括字母和数字|
### 方法2通过patch文件的方式
```bash
cd /opt/patch_workspace/
./make_hotpatch -i cmdline -p cmdline.patch
```
参数 | 说明|
--------- | --------|
-i |补丁ID可包括字母和数字|
-p |patch文件路径(patch文件必须支持在kernel-source路径下通过patch -p1的方式修改源码)|
补丁制作完成,补丁文件以压缩包的格式存放于/opt/patch_workspace/hotpatch目录下
## 制作第三方模块热补丁
支持两种方式制作第三方模块热补丁
### 方法1直接修改源代码的方式
进入模块源码目录(下面以https://gitee.com/openeuler/prefetch_tuning模块为例)
```bash
git clone https://gitee.com/openeuler/prefetch_tuning
cd prefetch_tuning
cp prefetch_mod.c prefetch_mod.c.new
```
此处cp操作的后缀.new在后面执行make_hotpatch时会用到
修改prefetch_mod.c.new中的函数
```bash
cd /opt/patch_workspace/
./make_hotpatch -d .new -i testmod -m `pwd`/prefetch_tuning/
```
参数 | 说明|
--------- | --------|
-d |前面cp操作时的唯一后缀名|
-i |补丁ID可包括字母和数字|
-m |第三方模块源码路径|
-f |可选当第三方模块Makefile不在-m指定的源码目录下时通过该参数指定Makefile的绝对路径|
### 方法2通过patch文件的方式
```bash
cd /opt/patch_workspace/
./make_hotpatch -i testmod -m `pwd`/prefetch_tuning/ -p testmod.patch
```
参数 | 说明|
--------- | --------|
-i |补丁ID可包括字母和数字|
-m |第三方模块源码路径|
-p |patch文件路径(patch文件必须支持在-m参数指定的路径下通过patch -p1的方式修改源码)|
-f |可选当第三方模块Makefile不在-m指定的源码目录下时通过该参数指定Makefile的绝对路径|
第三方模块补丁补丁制作完成,补丁文件以压缩包的格式存放于/opt/patch_workspace/hotpatch目录下
## 管理热补丁
### 加载热补丁
```bash
livepatch -l klp_cmdline.tar.gz
```
### 激活热补丁
```bash
livepatch -a cmdline
```
此时热补丁已生效,缺陷函数已被修复。
### 回退热补丁
```bash
livepatch -d cmdline
```
### 卸载热补丁
```bash
livepatch -r cmdline
```
## 编译更新补丁工具
```bash
yum install -y git rpm-build elfutils-libelf-devel gdb-headless
git clone https://gitee.com/src-openeuler/kpatch.git
mkdir -p ~/rpmbuild/SOURCES/
/bin/cp kpatch/* ~/rpmbuild/SOURCES/
rpmbuild -ba kpatch/kpatch.spec
rpm -Uvh ~/rpmbuild/RPMS/`arch`/kpatch*.rpm
rpm -Uvh ~/rpmbuild/RPMS/noarch/kpatch*.rpm
```
## 热补丁约束限制
### 不支持的函数修改行为
- 不支持修改函数参数或返回值类型或个数。
- 不支持删除函数。
- 不支持修改数据结构成员(热补丁原理是做函数替换)。
### 不支持的文件修改行为
- 不支持修改汇编文件。
- 不支持修改头文件。
- 不支持修改非C语言编写的文件。
### 不支持的变量修改行为
- 不允许删除全局变量或函数内部静态局部变量。
- 不支持修改全局变量或静态局部变量初始值。
- 不支持新增同名静态局部变量。
- 不支持修改多个同名静态局部变量的引用顺序。
### 不支持的函数类型
- 不支持对初始化函数打补丁(初始化函数只执行一次,补丁函数执行不到)。
- 不支持对死循环、不退出函数打补丁(旧函数不退出调用栈,没有机会调用新函数)。
- 不允许对NMI中断的处理函数打补丁 stop machine无法stop住NMI中断处理流程补丁无法保证对该类函数打补丁的一致性和安全性
- 不支持对修改前后内敛情况发生变化的函数打补丁。
- 不支持编译器生成的函数名称在修改前后发生变化的函数打补丁,例如修改前编译器生成的函数名为“ do_oops_enter_exit.part.0”,修改后编译器生成的函数名为“ do_oops_enter_exit”。
- 不支持对arm64架构下长度小于4条指令的超小函数打补丁。这种情况可以通过对外围函数打补丁来解决
- 不支持对启用ftrace、 kprobe等修改指令机制的函数打补丁。打热补丁会使被修改函数的ftrace/kprobe机制失效
- 不支持对以下idle进程相关函数打补丁
- `call_cpuidle`
- `cpuidle_idle_call`
- `do_idle`
- 不支持对包含以下弱符号的函数打补丁。
- `kallsyms_addresses`
- `kallsyms_num_syms`
- `kallsyms_names`
- `kallsyms_markers`
- `kallsyms_token_table`
- `kallsyms_token_index`
- `kallsyms_offsets`
- 不支持对包含下列范围之外的其他代码段的函数打补丁:
- ` .text`
- `__bug_table`
- `.fixup`
- `__ex_table`
- `__jump_table`
- `.smp_locks`
- `.parainstructions`
- `.altinstructions`
- 不支持在 `.altinstructions` 段中修改 `ALTINSTR_ENTRY_CB` 类型 `alt_instr` 的函数打补丁。例如 arm64 架构下 kvm 模块中的 kern_hyp_va 函数。