内核动态补丁(kpatch)及kpatch pushsection popsection previous的解释

2023-05-16

内核动态补丁(katch)解释

本文阅读体验不好,因此做了pdf版本,点击下载,如果你没有分数,可以直接留言找我要pdf版本。

内核可以在运行时动态执行补丁中的代码(kpatch),而不需要重启后再运行补丁代码。对于kpatch的运行原理,可以参看[3], kpatch基于ftrace技术,可以在内核运行时动态的(即不需要重启)、整体替换某个函数(但需要暂时停止所有运行时进程)。如图1所示,具体的,当内核运行之前,加入原来的内核函数名字为func_original(),则内核编译时就先把patch做好(假设替换函数为func_replace()),同时编译进内核中。注意,图1中Original Function部分大小要>=Replacement Function部分的大小,这也导致在kpatch相关代码中,会添加一些nop指令,这些nop指令的作用就是填充指令段,用于对齐原来的函数

图1 kpatch的过程[3]

 

本文主要解释从gnu汇编原语角度如何实现kpatch,具体kpatch机制可以参考文献[3]。内核文件arch/arm64/include/asm/alternative.h中有一段汇编,涉及内核动态patch技术,以此为例介绍如下:

 

关键词:Linux kernel, 动态补丁,kpatch, .pushsection, .popsection, .previous, .org

  1. 问题起源:

阅读代码__tlbi()[arch/arm64/include/asm/tlbflush.h]

图2 __tlbi()定义

 

追踪__tlbi()定义如图2所示,如果__tlbi()函数中带其他参数,例如__tlbi(vale1is, addr);则通过上述宏会翻译成__TLBI_1(),否则翻译成__TLBI_0()。上图中CONFIG_QCOM_FALKOR_ERRATUM_1009=1, ARM64_WORKAROUND_REPEAT_TLBI=17[arch/arm64/include/asm/cpucaps.h],这也可以从图4预处理结果看到继续追踪ALTERNATIVE的定义

  1. ALTERNATIVE定义如下:

arch/arm64/include/asm/alternative.h:

244 #define ALTERNATIVE(oldinstr, newinstr, ...)   \

245     _ALTERNATIVE_CFG(oldinstr, newinstr, __VA_ARGS__, 1)

 

 

63 #define _ALTERNATIVE_CFG(oldinstr, newinstr, feature, cfg, ...) \

64     __ALTERNATIVE_CFG(oldinstr, newinstr, feature, IS_ENABLED(cfg)) 

 

继续追踪__ALTERNATIVE_CFG定义

  1. __ALTERNATIVE_CFG的宏定义如下:

arch/arm64/include/asm/alternative.h

图3 __ALTERNATIVE_CFG的定义

图4 ALTINSTR_ENTRY和结构体alt_instr定义

 

为了理解上述宏定义,通过内核编译时修改编译选项-E得到预处理结果[4]如下:

图5 预处理结果

 

编译完成后如下:

图6 编译后结果

 

 

按照上述图3中宏定义,套入__tlbi(vale1is, addr),展开macro如下:

为了方便对比,把图3再次复制如下:

asm ("tlbi " "vale1is" ", %0\n"

       .if  1 == 1

              661:  

nop                  //insn1

          nop                  //insn1

              662:

.pushsection .altinstructions,  “a”      //把下述代码,填充图4结构体alt_instr

                             .word 661b - .  //存储被替换指令相对于当前地址的偏移:661b的地址减去当前地址(负)

                             .word 663f - .     //存储插入指令相对于当前地址的偏移:663f的地址减去当前地址(正)

                             .hword   17            //以16进制存储值17,特征位,用于区分该部分代码针对哪个bug

                             .byte 662b-661b      //存储被替换指令(两条nop)的长度

.byte 664f-663f        //存储插入指令的长度(<=被替换指令的长度)

                      .popsection                     //把指向当前section altinstructions的指针,再次指向栈中上一个section

                      .pushsection .altinstr_replacement, "a”  //把下述代码只读填充到section altinstr_replacement

              663:

                     dsb ish                       //insn2

        tlbi  “vale1is" ", %0"  //insn2

664:

.popsection  //把指向当前section altinstructions的指针,再次指向栈中上一个section

 

//判断长度insn1==insn2,注意上图中的注释

.org . - (664b-663b) + (662b-661b)      //当前地址-(664-663)+(662-661)

.org . - (662b-661b) + (664b-663b)      //当前地址-(662-661)+(664-663),

.endif

: :"r" (addr));  

 

上述代码就是一条asm嵌入汇编,但是其中包含了pushsecton/popsection等操作。

.pushsection .altinstructions,  “a”:这句意思是,在section altinstruction上面继续push,并swtich到altinstructions上继续操作(可以认为把指针指向altinstructions了),并且当前section属性为allocatable,类似于汇编指令rodata,read only。后续指令一直到popsection之前,都是为了填充结构体alt_instr,该结构体用于指导内核运行时替换原来的执行代码。

popsection: 作用是把上述指针指向执行pushsection之前的section,一般之前的section都是.data

 

具体的,可以参考摘自[8]的描述:

Operation

The .section directive switches the current target section to the one described by its arguments. The .pushsection directive pushes the current target section onto a stack, and switches to the section described by its arguments. The .popsectiondirective takes no arguments, and reverts the current target section to the previous one on the stack. The rest of the directives (.text.data.rodata.bss) switch to one of the built-in sections.

If continuing a previous section, and the flags, type, or other arguments do not match the previous definition of the section, then the arguments of the current .section directive will have no effect on the section. Instead, the assembler uses the arguments from the previous .section directive. The assembler does not currently emit a diagnostic when this happens.

 

  1. 关于__ALTERNATIVE_CFG宏的总结:

因此,上述pushsection和popsection的组合,思路是(以从.data section转换而来为例):从.data section转到当前altinstructions section,并以只读方式填充alt_instr(具体该结构的用法,请参考kpatch的实现[3]),然后把section指针再次指向.data section。再次从.data section跳转到altinstr_replacement,以只读方式填充该section,把未来将要用到的替换指令dsb/tlbi填充到当前section,再次退回到.data section。

 

真正动态使用该altinstr_replacement的流程:查询altinstructions section,获取用于补丁或替换原有指令的地址及偏移等信息(即alt_instr)通过该信息查询altinstr_replacement段,执行然后返回。

 

 

内核vmlinux.lds文件中对于两个段有定义:

crch/arm64/kernel/vmlinux.lds:

 

上述push/pop等操作就是对这两个section进行操作。

 

  1. .previous/popsection/pushsection使用说明

.previous:交换当前section和距离当前section最近的那个section的指针。如果连续使用两个previous,就会回到当前section

.puhsection  name: 把当前目标section(也就是pushsection后面跟着的section名name)压栈到name所在的section的顶部,然后把section指针指向name所在的section

.popsection :不需要参数,直接把指向当前section得指针,指向上一个section

 

 

  1. 为了进一步说明上述几个section操作,举例如下[10]:

.section A

.subsection 1

  # Now in section A subsection 1

  .word 0x1234

.section B

.subsection 0

  # Now in section B subsection 0

  .word 0x5678

.subsection 1

  # Now in section B subsection 1

  .word 0x9abc

.previous

  # Now in section B subsection 0

  .word 0xdef0

上述命令会把0x1234插入sectionA,0x5678和0xdef0插入sectionB中subsection0,把0x9abc插入sectionB的subsection1。

原因:当执行到.previous时,当前的section是 section subsection 1,那么,previous会交换当前的section和距离当前section最近的那个section(section B subsection0)的指针,因此会把0xdef0插入section B的 subsection0中。

 

  1. 综合例子2[11]:

.data      //进入section data,存储0

.byte 0

 .section A //进入sectionA,存储1

.byte 1

 .previous //再次进入section data,存储0

.byte 0

 .previous //再次进入section data之前的section(sectionA),存储1

.byte 1

 .pushsection B      //把sectionB中的2压栈,并把当前section指针指向section B,

.byte 2

 .previous       //进入section A,存储1

.byte 1

 .previous       //进入section B,存储2

.byte 2

 .pushsection C  //把section C中的3压栈,并把当前section指针指向section C,

.byte 3

 .previous      //进入section B,存储2

.byte 2

 .previous       //进入section C,存储3

.byte 3

 .popsection //弹出当前section C,恢复top层的section 指针,即进入section B,存储2

.byte 2

 .previous       //进入距离当前sectionB最近的那个section,即section A,存储1

.byte 1

 .previous       //进入距离当前section A最近的sectionB 存储2

.byte 2

 .popsection   //弹出当前section B,恢复top层section指针,进入sectionA,存储1

.byte 1

 .previous       //进入距离当前section A最近的section:data section,存储0

.byte 0

 .previous       //从data section 进入section A,存储1

.byte 1

 

上述操作,把所有的0值存储在.data section,把所有的1存储到section A,把所有的2存储到section B,把所有的3存储到section C

 

 

 

参考:

[1] https://en.wikipedia.org/wiki/Kpatch

[2] https://github.com/torvalds/linux/blob/master/arch/x86/include/asm/alternative-asm.h

[3] kpatch: https://en.wikipedia.org/wiki/Kpatch

[4] 内核预处理:http://ju.outofmemory.cn/entry/271369

[5] popsection: http://web.mit.edu/rhel-doc/3/rhel-as-en-3/popsection.html

[6] pushsection: http://web.mit.edu/rhel-doc/3/rhel-as-en-3/pushsection.html

[7] section: https://sourceware.org/binutils/docs/as/Section.html#Section

[8] push/pop section ARM官方解释:

http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0774i/bpl1510589893923.html

[9] push/previous example:http://www.sourceware.org/ml/binutils/2000-08/msg00043.html

[10] previous section操作举例:https://sourceware.org/binutils/docs/as/Previous.html#Previous

[11] previous section例2: https://www.sourceware.org/ml/binutils/2000-08/msg00043.html

 

 

 

 

 

 

 

477 CONFIG_QCOM_FALKOR_ERRATUM_1003=y                                                                                                                                                     

 478 CONFIG_QCOM_FALKOR_ERRATUM_1009=y

 479 CONFIG_QCOM_QDF2400_ERRATUM_0065=y

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

内核动态补丁(kpatch)及kpatch pushsection popsection previous的解释 的相关文章

  • MAVLink协议的移植

    mavlink协议被大众知晓应该是PX4项目发起之后 xff0c 随着开源飞控神器PX项目进入国内 本次就只分析移植过程中的问题 xff0c 协议具体内容及其他知识只稍作带过 xff0c 有时间再更新 mavlink的源码有官方的代码生成器
  • python函数变量的用法

    如果想要在一个函数内部来修改外部变量的值 有下面四种方法 a gt 通过返回值赋值 b gt 使用全局变量 c gt 修改list或dict对象的内部元素 d gt 修改类的成员变量 span class token comment ret
  • python常用模块大全

    1 time模块 span class token keyword import span time span class token operator span 一 span class token operator span span
  • 关于自定义比较函数 usort 如何使用 类中的方法

    关于自定义比较函数 usort xff0c 如果直接使用函数 xff0c 是 usort arr 34 yourfunction 34 如果要使用类中的自定义方法 xff0c 则用以下方式 xff1a lt php SortTest 64
  • Python软件编程等级考试四级——20220618

    Python软件编程等级考试四级 20220618 理论单选题判断题 实操第一题第二题第三题 理论 单选题 1 有如下Python程序 xff0c 包含lambda函数 xff0c 运行该程序后 xff0c 输出的结果是 xff1f g s
  • docker启动带xfce桌面和rdp服务的ubuntu

    docker run d p 3389 3389 scottyhardy docker remote desktop 默认用户名ubuntu xff0c 密码ubuntun https hub docker com r scottyhard
  • 10张图带你深入理解Docker容器和镜像

    编者的话 本文用图文并茂的方式介绍了容器 镜像的区别和Docker每个命令后面的技术细节 xff0c 能够很好的帮助读者深入理解Docker 扫VX 领Java资料 xff0c 前端 xff0c 测试 xff0c python等等资料都有
  • 13款Linux安全运维必备的实用工具

    本文介绍几款 Linux 运维比较实用的工具 xff0c 希望对 Linux 运维人员有所帮助 1 查看进程占用带宽情况 Nethogs Nethogs 是一个终端下的网络流量监控工具可以直观的显示每个进程占用的带宽 下载 xff1a ht
  • ros学习(六):geometry_msgs消息类型

    一 geometry msgs Pose 消息类型 http docs ros org en melodic api geometry msgs html msg Pose html http docs ros org en melodic
  • ISO 11519-2与ISO 11898-3之间的关系

    ISO 11519由以下部分组成 xff0c 总称 道路车辆 低速串行数据通信 xff1a Part 1 xff1a General and definitions 概述和定义 Part 2 xff1a Low speed controll
  • 《Autosar从入门到精通-实战篇》总目录_培训教程持续更新中...

    目录 一 Autosar入门篇 xff1a 1 1 DBC专题 xff08 共9篇 xff09 1 2 ARXML专题 xff08 共35篇 xff09 1 2 1 CAN Matrix Arxml xff08 共28篇 xff09 1 2
  • 【MCAL_CANDriver】-1.3-FullCAN和BasicCAN的差异及配置使用

    点击返回 Autosar MCAL高阶配置 总目录 目录 1 什么是FullCAN和BasicCAN 1 1 FullCAN Basic CAN HRH区别 1 2 FullCAN Basic CAN HTH区别 1 3 FullCAN和B
  • ROS学习1

    1 安装ros 我这里使用的是ros melodic这个版本 xff0c 具体安装可以参考其它教程 管理环境 printenv grep ROS 得到 ROS DISTRO 61 melodic ROS ETC DIR 61 opt ros
  • ROS学习1

    1 安装ros 我这里使用的是ros melodic这个版本 xff0c 具体安装可以参考其它教程 管理环境 printenv grep ROS 得到 ROS DISTRO 61 melodic ROS ETC DIR 61 opt ros
  • ubuntu18.04使用apt安装python3.7

    sudo apt update sudo apt install software properties common sudo add apt repository ppa deadsnakes ppa sudo apt install
  • c++读取自定义点云pcd文件

    之前查读取pcd的文件 xff0c 大多数是用python的open3d来进行读取 xff0c 但是这样读取到的信息 xff0c 好像只能够得到 pcd points 和pcd colors 但是如果想要把pcd中的信息都拿到呢 xff0c
  • lio-sam中点云地图保存

    在 src save map srv 中有如下的定义 float32 resolution string destination bool success 注意 下面指的是feedback xff0c 接下来看save map这个服务是如何
  • IoU-aware Single-stage Object Detector for Accurate Localization

    Motivation 从这张图里面可以很好地看出来作者的出发点 xff0c 即在目标检测里面 xff0c 分类的分数其实并不能够准确地反应框是否准确 像上面 xff0c 都是分类分数高 xff0c 而iou低的case 而真正iou高的框
  • SECOND: Sparsely Embedded Convolutional Detection

    contributions 应用sparse convolution 提升了训练以及inference的速度 提出一个novel 的angle loss 来回归yaw角 介绍了gt sampling的augmentation的方式 spar
  • Mac外接键盘ikbc win键无法使用问题

    ikbc的型号 是c87 青轴的 之前win键是可以用的 xff0c 今天发现不能用了 xff0c 查了一下 xff0c 原来是无意中按错被锁住了 按右下边的Fn 43 右上 PrtSc 即可解锁 又可以愉快地使用win键敲代码了

随机推荐

  • ros学习(七):sensor_msgs 消息类型

    一 sensor msgs Imu sensor msgs Imu Documentation http docs ros org en api sensor msgs html msg Imu html c 43 43 使用时头文件为 x
  • np.random.choice的用法

    import numpy as np 参数意思分别 是从a 中以概率P xff0c 随机选择3个 p没有指定的时候相当于是一致的分布 a1 61 np random choice a 61 5 size 61 3 replace 61 Fa
  • np.clip()的用法

    一时间忘了 xff0c 就又看了一下API 是这样说的 numpy clip a a min a max out 61 None source Clip limit the values in an array Given an inter
  • np.roll的用法

    coding UTF 8 import numpy as np np roll a shift axis 61 None 意思是将a xff0c 沿着axis的方向 xff0c 滚动shift长度 example1 a 61 np aran
  • 为什么vmware中的ctrl+alt+F1~F7不能用?

    这个总是确实困挠了我好久 xff0c 也花了我大把大把的时间去弄 xff0c 终于今天搞定了 xff0c 但是其实就2分钟就能搞定的事情 所以在此作总结 希望能帮助其他人 我的目的是想用Mac装上Vmware xff0c 然后在里面下ten
  • Squeeze-and-Excitation Networks 的理解

    SE Block 主要是考虑到了不同通道之间所占的重要性可能不一样 xff0c 而以前的网络中并没有考虑到这一点 xff0c 而是把所有通道的重要性当成一样来处理的 不同的通道的重要性是通过学到的一组权值来scale的 xff0c 相当于经
  • Gitee同步GitHub仓库如何操作

    最近 xff0c 许多开发者在进行私有仓库同步时 xff0c 会发现无法在 Gitee 通过同步功能拉取 GitHub 上的代码 xff0c 产生该问题的原因是 GitHub 从 2021 年 8 月 14 日后 xff0c 使用 Git
  • AUTOSAR ComM模块介绍

    AUTOSAR ComM模块介绍 Autosar ComM概述 Autosar ComM 全称是 Autosar Communication Manager 顾名思义就是用来管理通讯的 ComM 模块位于 BSW 中 Systme Serv
  • C语言中__FILE__ __LINE__ #line的用法

    C语言中 FILE LINE line的用法 C语言中 FILE 用于指示本行语句所在源文件的文件名 例如该行语句位于main c中 xff0c 则 FILE 表示main c C语言中 LINE 用于指示本行语句位于源文件中的位置即行数
  • 【新手向】make工具的使用

    make工具 在了解make工具前我们回顾下gcc编译步骤 1 xff09 预处理 处理与 号相关的代码 gcc E xxx c o xxx i 2 xff09 编译 检查语法错误 xff1b 如果语法有误则报错 xff0c 如果语法没错则
  • [python] python调用C++ 程序

    Python调用C C 43 43 程序的方法 最近写BUG的时候遇到python计算很慢的情况 xff0c 于是调研了一波在python中嵌入C 43 43 程序的方法 xff0c 记录一下 xff0c 便于查询 一般来说在python调
  • 深度学习(三):yolov5环境配置及使用

    目录 0 前言 1 环境配置 1 1 python环境 1 2 官方github的样例 1 2 1 打印检测结果 1 2 2 展示检测结果 2 运用detect py进行检测 2 1 网络摄像头 2 2 将检测过程可视化 3 运用train
  • sensor_data参数校验

    新的 xff1a Akamai sensor data zwl haley的博客 CSDN博客 只说下思路吧 xff0c 毕竟把加密代码公开对别网站不好 如有权益问题可以发私信联系我删除 xff0c 或q 1847858794 如图 xff
  • C++ muduo网络库知识分享01 - Linux平台下muduo网络库源码编译安装

    Muduo is a multithreaded C 43 43 network library based on the reactor pattern muduo库的介绍就是 xff1a 一个基于reactor反应堆模型的多线程C 43
  • FCT测试

    1 总论 2 启动过程 3 各模块实现 1 总论 FCT 作为 Android 的一个外来测试程序 xff0c 位于源码的 external 文件夹内 xff0c 其目的是作为产品在 PCBA 装配生产线中的一个制程 xff0c 对外围硬件
  • ARM上电启动及Uboot代码分析

    注意 xff1a 由于文档是去年写的 xff0c 内有多个图片 xff0c 上传图片很麻烦 xff08 需要截图另存插入等等 xff09 xff0c 我把文章的PDF版本上传到了CSDN下载资源中 为了给自己赚点积分 xff0c 所以标价2
  • 【解决】缺少libstdc++.so.6库的原因及解决办法

    问题原因 xff1a 系统是64bit xff0c 该库是32bit的 xff0c 在64bit系统上安装32bit库 解决办法 xff1a 1 查看哪个安装包包含该库 xff1a yum provides libstdc 43 43 so
  • 仿真器和模拟器的区别

    仿真器 xff08 emulator xff09 和模拟器 xff08 simulator xff09 是比较容易混淆的概念 xff0c 这两个概念不仅针对计算机体系结构 xff0c 在很多方面都有所应用 xff0c 例如航空模拟器 街机仿
  • Flush-Cache/Page-Lock/Flush-TLB说明

    Flush Cache Page Lock Flush TLB说明 理论上顺序 xff1a 获得页面锁 xff0c 保证后续flush操作完成之前不允许继续读写Flush cacheFlush tlb 以下用numa migrate pag
  • 内核动态补丁(kpatch)及kpatch pushsection popsection previous的解释

    内核动态补丁 xff08 katch xff09 解释 本文阅读体验不好 xff0c 因此做了pdf版本 xff0c 点击下载 xff0c 如果你没有分数 xff0c 可以直接留言找我要pdf版本 内核可以在运行时动态执行补丁中的代码 xf