Hello DLWorld 专注

kpatch

Kpatch是Redhat的一个内核热补丁框架,主要用于修复内核安全漏洞和稳定性bug,不能用于大的内核版本升级。另外两个类似的项目是Oracle的Ksplice和SUSE的kGraft。

Kpatch

Kpatch是Redhat的一个内核热补丁框架,主要用于修复内核安全漏洞和稳定性bug,不能用于大的内核版本升级。另外两个类似的项目是Oracle的Ksplice和SUSE的kGraft。

限制:

  • 数据结构变化、边界情况无法处理
  • stop_machine()延时1-40ms

快速使用

  1. 安装依赖
    # yum install rpmdevtools pesign yum-utils openssl wget numactl-devel
    
  2. 编译kpatch和kpatch-build
    # git clone https://github.com/dynup/kpatch
    # cd kpatch/
    # make; make install
    
  3. 测试补丁
    # cat kpatch-meminfo.patch
    diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
    index ade4e42..97252cc 100644
    --- a/fs/proc/meminfo.c
    +++ b/fs/proc/meminfo.c
    @@ -131,7 +131,7 @@ static int meminfo_proc_show(struct seq_file *m, void *v)
                 "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
    
  4. 编译模块 包括获取源码、测试补丁、读取特殊段数据、编译原始内核、
    # kpatch-build -s ~/rpmbuild/BUILD/kernel-3.10.0-327.28.3.el7/linux-3.10.0-327.28.3.el7.x86_64/ -v /usr/lib/debug/usr/lib/modules/3.10.0-327.28.3.el7.x86_64/vmlinux  kpatch-meminfo.patch
    Using source directory at /root/rpmbuild/BUILD/kernel-3.10.0-327.28.3.el7/linux-3.10.0-327.28.3.el7.x86_64
    Testing patch file
    checking file fs/proc/meminfo.c
    Reading special section data
    Building original kernel
    Building patched kernel
    Extracting new and modified ELF sections
    meminfo.o: changed function: meminfo_proc_show
    Patched objects: vmlinux
    Building patch module: kpatch-kpatch-meminfo.ko
    SUCCESS
    
  5. 加载补丁模块
    # kpatch replace kpatch-kpatch-meminfo.ko 
    loading core module: /usr/local/lib/kpatch/3.10.0-327.28.3.el7.x86_64/kpatch.ko
    loading patch module: kpatch-kpatch-meminfo.ko
    
  6. 检查结果
    # kpatch list
    # grep -i chunk /proc/meminfo 
    VMALLOCChunk:   34359337092 kB
    

基本原理

kpatch包括编译补丁生成模块的kpatch-build和加载补丁模块的kpatch两个组件。

内涵打补丁步骤:

  1. 将新函数加载到内存
  2. 将新函数链接到内核,需要允许访问未导出的内核符号
  3. 安全检查(Active Safeness Check)
    • 防止新旧函数同时运行
    • stop_machine()和栈检查
  4. 使用ftrace打补丁

引用计数器

切换到新函数的时机,由引用计数器(refcount)控制。在热补丁期间允许函数继续被调用,但增加一个原子引用计数器,函数入口处引用计数增加,函数退出时计数减一。当引用计数为0时,更新所有函数路径。函数进入或退出通过kretprobe hook。

安全性检查

在上下文切换时执行运行安全性检查(Active Safeness Check),通过kprobe hook上下文切换。 两阶段检查:

  1. 检查休眠的任务。
  2. 检查运行中的任务。

参考