diff --git "a/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_01.png" "b/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_01.png" new file mode 100644 index 0000000000000000000000000000000000000000..6f882a1b9553b7d1d39f311322e3b9f4c7eea13b Binary files /dev/null and "b/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_01.png" differ diff --git "a/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_02.png" "b/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_02.png" new file mode 100644 index 0000000000000000000000000000000000000000..5334fccf33d0e6f97eeac0827ccd599f2d4f5e3b Binary files /dev/null and "b/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_02.png" differ diff --git "a/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_03.png" "b/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_03.png" new file mode 100644 index 0000000000000000000000000000000000000000..4e7b658ee5fea204677562524ee3a9d60e61164c Binary files /dev/null and "b/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_03.png" differ diff --git "a/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_04.png" "b/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_04.png" new file mode 100644 index 0000000000000000000000000000000000000000..11ee529a7d7da5735de13a255a4356efb3e78705 Binary files /dev/null and "b/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_04.png" differ diff --git "a/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_05.png" "b/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_05.png" new file mode 100644 index 0000000000000000000000000000000000000000..cbd9145ed8c6cfc3e143a3a5ca66741cb48a266c Binary files /dev/null and "b/sig/Cloud_Kernel_Sig/assets/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\263\225/img_05.png" differ diff --git "a/sig/Cloud_Kernel_Sig/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\241\210.md" "b/sig/Cloud_Kernel_Sig/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\241\210.md" new file mode 100644 index 0000000000000000000000000000000000000000..369027ac3f4650760215ba6610391a208eb43f68 --- /dev/null +++ "b/sig/Cloud_Kernel_Sig/content/\347\244\276\345\214\272\347\240\224\345\217\221\351\241\271\347\233\256/\345\206\205\346\240\270\351\251\261\345\212\250/KABI\346\243\200\346\265\213\346\226\271\346\241\210.md" @@ -0,0 +1,103 @@ +# 背景 + +KABI(Kernel Application Binary Interface)内核应用二进制接口,它定义了内核和用户空间应用程序之间的二进制接口规范,是一套内核提供给驱动或者其他模块调用的接口。内核在保障KABI不变的情况下可以是得OOT(out of tree)模块在新的内核版本上不用重新编译即可安装使用。可有效地降低OOT模块适配新内核的人力投入。 + +为了保证KABI内核的KABI不发生变化,需要在每次在修改代码时对内核KABI进行检测,目前主要的KABI检测方案有两种:一种是通过kabi-dw开源软件检测内核的KABI;另一种是check-kabi检测内核的KABI。这两种方案都是通过对比与基线符号信息来判断内核的KABI是否被破坏。 + +# kabi-dw + +kabi-dw工具是一款开源的内核KABI检查工具,它可以对内核合入补丁前后编译的结果生成函数接口原型、关联结构体、关联枚举等对比信息,然后通过对比前后生成的对比信息来检查KABI是否被破坏,并显示出具体破坏的地方。主要流程如下。 + +![](../../../assets/内核驱动/KABI检测方案/img_01.png) + +这里主要涉及两个重要的流程,内核符号信息的生成,符号的对比。 + +## 1、内核符号信息的生成 + +kabi-dw会根据kabi白名单生成函数接口原型、关联结构体、关联枚举等对比信息,使用方法如下。 + +`kabi-dw generate -s kabi_whitelist_x86_64 –o kabi_after_x86_64 /lib/modules/4.19.91` + +这里边generate为要执行的kabi-dw命令,表示要生成符号信息。 + -s 用来指定使用的白名单 + -o 用来指定符号信息输出的目录 + 最后需要指定内核编译生成的产物目录。 + +具体的流程如下: + +![](../../../assets/内核驱动/KABI检测方案/img_02.png) + +具体流程如下: + +1)解析命令行参数:kabi-dw通过解析传递给它的命令行参数来确定要生成报告的目标内核版本和其他配置信息。 + +2)walk_dir函数首先通过scandir然后遍历所有的文件,对获取每个文件中的导出符号信息。 + +3)读取目标内核的符号文件:kabi-dw需要读取目标内核的符号文件(通常是vmlinux文件或.ko模块文件),以获取内核中的符号信息。它使用process_symbol_file函数来处理每个符号文件。 + +4)处理符号文件:对于每个符号文件,kabi-dw会依次执行以下步骤: + + 验证文件类型:kabi-dw会检查文件类型,只处理.ko模块文件和vmlinux文件,如果是其他类型的文件,则跳过处理。 + + 检查rhel构建缓存目录:如果配置中指定了rhel构建缓存目录,kabi-dw会跳过这些目录,以避免处理不相关的文件。 + + 打开ELF文件:kabi-dw使用elf_open函数打开符号文件,并检查是否成功打开。 + + 获取符号表和别名表:kabi-dw使用elf_get_exported函数获取符号文件中的导出符号表和别名表。 + + 检查符号表是否为空:如果符号表为空,则跳过处理该文件。 + + 合并别名表:kabi-dw会将符号表和别名表进行合并,以确保所有符号都能被正确处理。 + + 初始化文件上下文:kabi-dw会初始化一个文件上下文结构体,用于保存符号文件的相关信息和配置。 + + 处理类型信息:kabi-dw会调用generate_type_info函数,根据符号信息生成类型信息。 + + 处理未找到的符号:kabi-dw会调用ksymtab_for_each函数,遍历符号表中的每个符号,对于未找到的符号,调用process_not_found函数进行处理。 + + 检查是否全部完成:如果所有的处理都完成了,kabi-dw会设置返回值为WALK_STOP,表示停止处理该符号文件。 + + 清理资源:释放符号表和别名表的内存,关闭ELF文件。 + +5)输出报告:最后,kabi-dws会将生成的报告写入指定的输出文件中。 + +## 2、KABI检查 + +使用kabi-dw检查内核KABI是否被破坏,命令如下。 + +`kabi-dw compare –k /tmp/kabi_test/kabi-whitelist/kabi_dw_output/kabi_pre_x86_64 kabi_after_x86_64` + +实现流程如下: + +![](../../../assets/内核驱动/KABI检测方案/img_03.png) + +在使用kabi-dw检测kabi是否被破坏时,需要指定基线kabi目录和内核编译后生成的符号文件目录,具体流程如下: + +1)参数解析。Kabi检测前,需要获取基线文件目录和内核编译后生成的符号文件目录。这两个目录里边的文件组织形式是一致的。 + +2)walk_dir函数首先通过scandir然后遍历所有的文件,对每一个文件进行kabi的校验。Kabi的校验是通过compare_files_cb函数实现的。 + +3)compare_files_cb函数会获取到要对比的文件名,然后调用compare_two_files函数。 + +4)compare_two_files函数首先会根据要对比的文件名,分别获取该文件在基线符号目录中的绝对路径。然后分别读取获取两个文件的内容,最后对比获取到的两个文件的信息和内容,信息和内容一致,说明kabi未被破坏;否则,kabi被破坏,并且输出破坏内容。 + +# check-kabi + +check-kabi是使用python编写的一个KABI检测脚本,用于检查内核模块的二进制接口是否发生了变化。它会检查当前版本的内核与基线版本之间的 ABI(应用程序二进制接口)的兼容性。 + +脚本会通过新版本内核的 Module.symvers 文件与基线符号信息来判断内核的KABI是否发生了变化,基线符号信息是通过kabi白名单从Module.symvers文件中获取到的。 + +Module.symvers文件是Linux内核编译时生成的,用于存储模块中导出的全局符号,供其他模块调用,在这个文件中保存了大量通过EXPORT_SYMBOL导出的全局符号。在编译模块时,内核构建系统会自动将模块导出的符号和版本信息记录到 Module.symvers 文件中。Module.symvers 文件的内容是以行为单位的文本格式,每一行记录了一个符号的相关信息,包括符号名、版本号和 CRC(循环冗余校验)值等,具体如下图所示。这些信息用于在模块加载时进行符号兼容性检查。 + +![](../../../assets/内核驱动/KABI检测方案/img_04.png) + +具体检查命令如下 + +`check-kabi -k Module.kabi -s Module.symvers` + +Module.kabi为基线版本的符号信息,Module.symvers为当前内核编译出来的Module.symvers。 + +检测流程: + +![](../../../assets/内核驱动/KABI检测方案/img_05.png) +