记录一次内核热补丁制作流程

最近接到下游的一个需求,要为适配某网卡修改内核的patch制作热补丁。内核热补丁有较多的约束限制,包括不支持修改数据结构,不允许删除函数内部静态局部变量,不支持头文件修改等等。本次要修改的patch包含了头文件的修改,数据结构的变动,如果要制作热补丁就需要将这些变动尽量移动到.c文件中。本次patch涉及两处数据结构的变化,分别如下:

+++ b/include/net/bonding.h
@@ -173,7 +173,8 @@ struct slave {
     u8     backup:1,   /* indicates backup slave. Value corresponds with
                   BOND_STATE_ACTIVE and BOND_STATE_BACKUP */
            inactive:1, /* indicates inactive slave */
-           should_notify:1; /* indicateds whether the state changed */
+           should_notify:1, /* indicates whether the state changed */
+           should_notify_link:1; /* indicates whether the link changed */
     u8     duplex;
     u32    original_mtu;
     u32    link_failure_count;
@@ -2249,6 +2271,12 @@ struct netdev_notifier_changeupper_info {
         struct net_device *upper_dev; /* new upper dev */
         bool master; /* is upper dev master */
         bool linking; /* is the nofication for link or unlink */
+     void *upper_info; /* upper dev info */
+};

一个是在结构体中新增一个位域成员,patch中对这个位域成员有读取和写的操作。为保持结构体不变,可以通过位运算从当前字节中获取到该位置的值。对应的获取和写这个位的操作可以用宏来实现,如下所示:

#define SET_SHOULD_NOTIFY_LINK_BIT(pslave, value) \
        (value) == 1 ? (*(char *)(&(pslave)->new_link + 1) |= 0x8) : (*(char *)(&(pslave)->new_link + 1) &= 0x7)

#define GET_SHOULD_NOTIFY_LINK_BIT(pslave)  ((*(char *)(&(pslave)->new_link + 1) & 0x8) >> 3)

另外一个结构体是新增了一个指向void类型的指针,搜索该patch所有引用这个结构体的地方,发现所有使用该结构体时,在函数中传的参数为该结构体的第一个成员,而不是整个结构体。如下所示。

void netdev_upper_dev_unlink(struct net_device *dev,
                 struct net_device *upper_dev)
{
        struct netdev_notifier_changeupper_info changeupper_info;
        changeupper_info.upper_dev = upper_dev;
        changeupper_info.master = master;
        changeupper_info.linking = true;
+      changeupper_info.upper_info = upper_info;
+      ret = call_netdevice_notifiers_info(NETDEV_PRECHANGEUPPER, dev,
+                       &changeupper_info.info);

这样就可以通过新增一个与netdev_notifier_changeupper_info 结构体相同的结构体定义, 将新增的成员upper_info传入即可,并且可以保持与原有的代码保持兼容,上述修改可以改为:

void netdev_upper_dev_unlink(struct net_device *dev,
                 struct net_device *upper_dev)
{
        struct netdev_notifier_changeupper_info_ext changeupper_info;
        changeupper_info_ext.upper_dev = upper_dev;
        changeupper_info_ext.master = master;
        changeupper_info_ext.linking = true;
+      changeupper_info_ext.upper_info = upper_info;
+      ret = call_netdevice_notifiers_info(NETDEV_PRECHANGEUPPER, dev,
+                       &changeupper_info_ext.info);

保持原有结构体netdev_notifier_changeupper_info 不变,新增一个netdev_notifier_changeupper_info_ext结构体。

若要不修改结构体的定义,那么就要满足在使用这个新增成员时,可以通过原有结构体找到该成员,并且要保证所有调用的函数参数接口不变化,一般来讲要保证这些比较困难,但是netdev_notifier_changeupper_info这个结构体的原有定义,以及原有的使用方式,可扩展型很好,就比较方便修改为结构体不变化的形式,满足制作内核热补丁的条件。

解决了这两个问题后,用这个patch制作热补丁,但热补丁没有制作成功,经过专家定位,主要问题在于,同一个patch中的修改涉及到编译到内核模块的,和编译到内核的。需要把它们进行拆分,要每个patch可以单独编译通过,完成独立的一块功能。并且还要保证修改的头文件不能又被内核模块调用,又被内核调用,否则头文件也要拆分到.c中。后面经过了各种拆分,把大量的在头文件中,或者在.c文件中定义的函数,或函数实现,挪到了引用的.c中,费了较大力气才把这个补丁给做出来了,由于拆分的代码太多,有太多的函数挪用,就给这个修改带来了较大的功能和可靠性的风险。

所以制作热补丁的方案还需要继续研究,如果后面能有更好的制作热补丁的方式,可以支持结构体变化,支持头文件变化,那么对内核的修改和调试将会大大缩短开发时间。

原文地址:https://www.cnblogs.com/xingmuxin/p/9087200.html

时间: 2024-07-31 16:05:38

记录一次内核热补丁制作流程的相关文章

[硬货分享] Linux 4.1 内核热补丁成功实践

好久不见的干货重现江湖!今日的内容是基于UCloud运维同学反馈的个别宿主机上存在进程CPU峰值使用率异常现象问题进行的相关阐述.本文详细介绍了该问题的完整分析思路和用热补丁的方式成功解决此问题的实践分享,如果觉得还不错,欢迎点赞分享!正文开始~ 最开始公司运维同学反馈,个别宿主机上存在进程CPU峰值使用率异常的现象.而数万台机器中只出现了几例,也就是说万分之几的概率.监控产生的些小误差,不会造成宕机等严重后果,很容易就此被忽略了.但我们考虑到这个异常转瞬即逝.并不易被察觉,可能还存在更多这样的

零代价修复海量服务器的内核缺陷——UCloud内核热补丁技术揭秘

下述为UCloud资深工程师邱模炯在InfoQ架构师峰会上的演讲——<UCloud云平台的内核实践>中非常受关注的内核热补丁技术的一部分.给大家揭开了UCloud云平台内核技术的神秘面纱. 如何零代价修复海量服务器的Linux内核缺陷? 对于一个拥有成千上万台服务器的公司,Linux内核缺陷导致的死机屡见不鲜.让工程师们纠结的是,到底要不要通过给服务器升级内核来修复缺陷?升级意味者服务器重启.业务中断以及繁重的准备工作:不升级则担心服务器死机,同样造成业务中断和繁重的善后工作. 而在今天的云计

基于自适应热补丁的Android内核漏洞生态修复方案

1. 背景 Android内核漏洞严重影响了Android平台的安全.一旦内核被攻破,所有依赖内核完整性的安全机制都岌岌可危(比如加密.进程隔离.支付.指纹验证等).作为Android平台最后的防线,TrustZone也会受到威胁,因为内核可以从很多被信任的接口向TrustZone发起攻击.因此,理想情况下Android生态圈应该及时消灭内核漏洞.然而从Google的Android Security Bulletin上看,Android内核漏洞的数量呈飞快上涨的趋势(Figure 1所示).虽然

linux下实现在程序运行时的函数替换(热补丁)【转】

转自:http://www.cnblogs.com/leo0000/p/5632642.html 声明:以下的代码成果,是参考了网上的injso技术,在本文的最后会给出地址,同时非常感谢injso技术原作者的分享. 但是injso文章中的代码存在一些问题,所以后面出现的代码是经过作者修改和检测的.也正因为这些错误,加深了我的学习深度. 最近因为在学习一些调试的技术,但是很少有提到如何在函数运行时实现函数替换的. 为什么会想到这一点?因为在学习调试时,难免会看到一些内核方面的调试技术,内核中的调试

Android 热补丁技术——资源的热修复

前言 今年真是热补丁框架的洪荒之力爆发的一年,短短几个月内,已经出现了好几个热修复的框架了,基本上都是大同小异,这里我就不过多的去评论这些框架.只有自己真正的去经历过,你才会发现其中的 大写的坑 事实上,现在出现的大多数热修复的框架,稳定性和兼容性都还达不到要求,包括阿里的Andfix,据同事说,我们自己的app原本没有多少crash,接入了andfix倒引起了一部分的crash,这不是一个热修复框架所应该具有的"变态功能".虽然阿里百川现在在大力推广这套框架,我依旧不看好,只是其思路

MinHook测试与分析(x86下 E8,E9,EB,CALL指令测试,且逆推测试微软热补丁)

依稀记得第一次接触Hook的概念是在周伟民先生的书中-><<多任务下的数据结构与算法>>,当时觉得Hook的本质就是拦截,就算到现在也是如此认为. 本篇文章是在x86下测试与分析跳转+offset类型的Hook,并且逆推测出热补丁的简单用法,MinHook它的中心就是覆盖重写并且可以复原.知道大概的思路后后让我们先来具体的实现MinHook再去做测试. 首先是堆的申请,这是必要也必须做的,对于微软函数HeapCreate()就不再赘述,以下是实现与卸载 1 NTSTATUS

[原创]MinHook测试与分析(x64下 E9,EB,CALL指令测试,且逆推测试微软热补丁)

依稀记得第一次接触Hook的概念是在周伟民先生的书中-><<多任务下的数据结构与算法>>,当时觉得Hook很奇妙,有机会要学习到,正好近段日子找来了MiniHook,就一起分享一下. 本篇文章是在x64下测试与分析jmp+offset类型的Hook,并且逆推测出热补丁的简单用法,MinHook它的中心就是覆盖重写并且可以复原.知道大概的思路后后让我们先来具体的实现MinHook再去做测试. 首先是堆的申请(申请PAGE_SIZE大小自动生长的堆),以下是实现与卸载 1 NTS

Android 热补丁动态修复框架小结

转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/49883661: 本文出自:[张鸿洋的博客] 一.概述 最新github上开源了很多热补丁动态修复框架,大致有: https://github.com/dodola/HotFix https://github.com/jasonross/Nuwa https://github.com/bunnyblue/DroidFix 上述三个框架呢,根据其描述,原理都来自:安卓App热补丁

Android热补丁动态修复技术(四):自动化生成补丁——解决混淆问题

一.前言 在上一章中,我们使用javassist成功为项目注入了System.out.println(AntilazyLoad.class);这行代码,解决了class_ispreverified问题,可以正常使用了,但肯定还存在着很多未知的问题. 首先是javassist的问题 class中使用到的类,必须添加到classpool的classpath中,我在Demo中写了一个自定义控件,注入代码的时候报错,提示没有找到Context,然后我将android.jar整个添加到classpath之