Kpatch 使用过程及其原理
2015-07-24 15:14
585 查看
1、简介
给 Linux 内核动态打补丁而不必重启系统是最近的一项 热点技术 。 虽然此前已经有了Ksplice 来达到此类目
的 , 但最近 SUSE 和 Redhat 却先后推出了类似的项目 。 其中,前者为
kGraft, 后者是
kpatch。
kGraft : 为了使 Linux 管理人员更容易的安装重要的 Kernel 安全补丁,同时又不让系统宕机,SUSE Labs 开发了 kGraft。kGraft
使用一组diff文件来计算内核中需要修改的部分。Kgraft在做替换时,不需要完全停止内核。 在打补丁时,正在运行的函数可以先使用老版本或新内核中对应的部分,当补丁打完后就可以完全切换新的版本。
kpatch : Redhat 目前已经以 GPLv2 许可发布了kpatch 的源代码 ,其主要包含以下 4 个组件 :
kpatch-build: 用来将 source diff patch 转换成 hot patch module;
hot patch module: 包含替代函数及原始函数元数据的内核模块;
kpatch core module: 为 hot patch 注册新的函数以用于替换提供接口的内核模块;
kpatch utility: 允许用户管理 hot patch 模块的命令行工具;
Kpatch运行时并不将内核调用重定向到老版本。相反,它会等待所有函数调用都停止时,再切换到新内核。Red Hat的工程师认为这种方法更为安全,且更容易维护,缺点就是在打补丁的过程中会带来更大的延迟。
2、Kpatch 详解
下面我们就来详细的看一下Kpatch的使用过程及原理:安装:
必备条件(由于kpatch 是由 rethat 开发的所以这里我们使用其官方推荐的linux发行版 fedora 21 ):
安装编译kpatch需要的的依赖包:
sudo yum install gcc kernel-devel elfutils elfutils-devel
安装“kpatch-build”所需的依赖包:
sudo yum install rpmdevtools pesign yum-utils openssl wget numactl-devel sudo yum-builddep kernel sudo debuginfo-install kernel # optional, but highly recommended sudo yum install ccache ccache --max-size=5G
克隆 kpathc 仓库:
$ git clone https://github.com/dynup/kpatch.git[/code]
编译:<span style="font-size:14px;">$ make</span>
安装(默认安装到 /usr/local 目录下):<span style="font-size:14px;">$ </span>sudo make install
测试 ——这里我们使用仓库自带的例子对kaptch进行测试wangye@debian:~/kaptch/kpatch-master/test/integration$ cat meminfo-string.patch Index: src/fs/proc/meminfo.c =================================================================== --- src.orig/fs/proc/meminfo.c +++ src/fs/proc/meminfo.c @@ -95,7 +95,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</span>
构建模块:$ kpatch-build -t vmlinux meminfo-string.patch
在这个过程中会在该目录下产生一个名为“meminfo-string.ko”的模块:
将该模块应用到正在运行的内核中:$ sudo kpatch load kpatch-meminfo-string.ko loading core module: /usr/local/lib/modules/3.13.10-200.fc20.x86_64/kpatch/kpatch.ko loading patch module: kpatch-meminfo-string.ko
检查模块是否成功载入:$ sudo kpatch load kpatch-meminfo-string.ko loading core module: /usr/local/lib/modules/3.13.10-200.fc20.x86_64/kpatch/kpatch.ko loading patch module: kpatch-meminfo-string.ko
还原更新:<span style="font-size:14px;">kpatch unload <code>kpatch-meminfo-string</code></span>kpatch 原理:
kpatch 主要有两个组件 katch build 和 katch.ko
katch build — 主要用来建立一个二进制的 patch 模块
katch.ko — katch产生的内核模块
kpatch 提供了一个 kaptch_register() 的接口函数主要用来为 “patch modules” 作函数替换,即: 该接口函数的主要作用是将旧函数用新函数替换掉(这里的新函数就是我们要打的补丁函数)。
kpatch 使用Ftrace 进行打补丁的操作
使用hook 链接到目标函数寄存器
修改 regs->ip 指针,将其指向新函数
考虑如下两个问题是否会出现?
如果需要打补丁的函数正在执行,kaptch 将如何操作?
新的函数和旧的函数是否会同时执行?
为了避免以上两个问题的出现,kaptch 在运行过程中会确保旧函数不被执行( 使用 stop_machine() 检查栈):
其大致流程如下:
补丁进程 增加一个ftrace 跟踪项(eg:foo() 函数),追踪哪些进程使用旧foo()函数;
调用 stop_machine 停止所有正在运行的进程和中断,并且遍历
stop_machine 的返回值,用来确保旧的foo() 函数确实已经被停止。检查旧的 foo() 函数在栈中的位置
更新hash 表,使函数调用栈中的指针指向新的 foo()函数,但是旧的foo()函数的指针地址保留方便还原。
参考:
https://lwn.net/Articles/597123/
相关文章推荐
- VS2008中编译通过,但调试时出现“未使用调试信息生成二进制文件”的问题
- html中 id属性和name属性区别
- 杭电 1002 A + B Problem II
- 原子操作的实现原理
- HDOJ 1232 畅通工程(并查集)
- jquery outerHeight方法 outerWidth方法
- 在Linux上安装Memcached服务(转)
- 有gridview汇出word和excel
- oracle,通过plsql创建用户表空间和所属用户示例
- leetcode第11题
- 国内外智慧医疗云平台调研
- using Camel in a Web Application
- using Camel in a Web Application
- php文件上传之多文件上传
- HDOJ 5294 Tricks Device 最短路(记录路径)+最小割
- iWatch报错: Authorization request cancled
- EditText不可编辑
- /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by ./xxxx
- GSMM数据库设计小结
- MYSQL---多表更新