通过内核编译法向Linux内核添加系统调用

Posted jhjgarden

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过内核编译法向Linux内核添加系统调用相关的知识,希望对你有一定的参考价值。

 

【实验内容】:

  向Linux添加一个系统调用
  测试该系统调用
  使用ptrace或类似的系统跟踪工具来对该测试程序进行跟踪调试

【软件】:VMWare支持的Ubuntu虚拟机 VSCode

【步骤】

1.在实验之前先下载好相关软件包

不过如果升级了make以后,如果内核版本低,会报错

1.    sudo apt-get install make  
2.    sudo apt-get install gcc  
3.    sudo apt-get install libncurses5-dev  
4.    sudo apt-get install flex  
5.    sudo apt-get install bison  
6.    sudo apt-get install libssl-dev  
7.    sudo apt-get install libelf-dev
2.进入 /usr/src下载内核源码(实验所用源码为 linux-5.5.7)
内核5.5.7所需要的存储空间特别大!!!一定要提前准备好!!!
1.    cd /usr/src  
2.    wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.5.7.tar.xz  

3.下载好之后在当前目录进行解压

1.    tar -xvf linux-5.5.7.tar.xz  

4.编写系统调用的入口表

1.    sudo vim linux-5.5.7/arch/x86/entry/syscalls/syscall_64.tbl  

添加

1.    335     common      mysyscall        __x64_sys_mysyscall

技术图片

 

 5.编写系统调用函数声明

1.    sudo vim linux-5.5.7/include/linux/syscalls.h

在里面添加

1.    asmlinkage long sys_mysyscall(int number);

技术图片

 

 6.实现系统调用函数

1.    sudo vim linux-5.5.7/kernel/sys.c

在里面添加

1.    SYSCALL_DEFINE1(mysyscall, int, number) {  
2.        int result = number * number * number;  
3.        printk("The result is %d
", result);  
4.        return 0;  
5.    }  

7.重新编译内核

1.    cd linux-5.5.7/                            //进入内核文件夹
2.    sudo cp /usr/src/linux-headers-5.3.0-40-generic/.config /usr/src/linux-5.5.7 //复制内核配置
3.    make mrproper                                //删除以前编译产生的垃圾文件  
4.    make clean    
5.    make menuconfig                              //选择Save保存再Exit
6.    make -j4                                     //编译内核  
7.    make modules_install                         //安装模块  
8.    make install                                 //安装内核  

技术图片

 

 技术图片

 

 8.重启选择linux-5.5.7进入

(因为linux系统会自动选择高版本内核加载,因此重启虚拟机后加载的内核就是刚刚编译完成的5.5.7内核)

技术图片

 

 9. 编写测试程序test.c验证系统调用是否成功

1.    #include <stdio.h>  
2.    #include <sys/ptrace.h>  
3.    #include <sys/types.h>  
4.    #include <sys/wait.h>  
5.    #include <sys/user.h>  
6.    #include <sys/reg.h>  
7.    #include <sys/syscall.h>  
8.    #include <unistd.h>  
9.    #include <linux/kernel.h>  
10.      
11.    int main () {  
12.        syscall(335,4);  
13.        return 0;  
14.    }  

编译执行后用dmsg查看结果

技术图片

 

 正确哒!!!

10.用strace进行追踪

技术图片

 

 能看到系统调用成功

11.常见错误汇总!!

我太难了我编译了五次才成功!

make首先,一定要在解压好的文件夹里make,内核也一定解压到那个文件夹!!!千万不能自己创一个文件夹写那个名字!!!我有个朋友这么干的哈哈哈哈

最常见的错误就是包没装全,如果报错就装就好了。

然后在make -4j之前,一定要检查一下有没有问题,因为make -4j一旦失败enmmmmmm。。。我的方法就是不sudo输入make -4j,这样除了权限报错以外,别的错误也会报错

之后就是内核编译的错误了

它是这样报错的:

[root@localhost module]# make 

make -C /opt/kangear/kernel/linux-2.6.32.2 M=/root/桌面/kangear/module modules

make[1]: Entering directory `/opt/kangear/kernel/linux-2.6.32.2‘

 

  ERROR: Kernel configuration is invalid.

         include/linux/autoconf.h or include/config/auto.conf are missing.

         Run ‘make oldconfig && make prepare‘ on kernel src to fix it.

 

 

  WARNING: Symbol version dump /opt/kangear/kernel/linux-2.6.32.2/Module.symvers

           is missing; modules will have no dependencies and modversions.

 

  Building modules, stage 2.

/opt/kangear/kernel/linux-2.6.32.2/scripts/Makefile.modpost:42: include/config/auto.conf: 没有那个文件或目录

make[2]: *** 没有规则可以创建目标“include/config/auto.conf”。 停止。

make[1]: *** [modules] 错误 2

make[1]: Leaving directory `/opt/kangear/kernel/linux-2.6.32.2‘

make: *** [all] 错误 2

[root@localhost module]# 

 

内核配置文件.config出错。

可以参照一下这个博客https://blog.csdn.net/u013225150/article/details/48272853

另外,这个博客的错误我也都遇到了https://blog.csdn.net/stranger00001/article/details/84637032?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

然后总结一下我这五次编译的卑微过程吧……
0.编译前因为安装包不全,在make -4j之前失败了很多次
1.第一次编译,因为在写程序的时候用了for函数,编译时并不支持,导致失败
2.去掉for函数之后,显示找不到配置的.config文件,发现make menuconfig的操作有误,内核配置文件的命令输入同样错误,并没有把内核配置成功复制
3.配置好内核,把所有相关包检查升级后再次编译,出现pkg错误,上网查资料后发现是make版本过高,一开始选择的4.18内核不支持
4.选择最新的5.5.7内核进行编译,因为虚拟机空间不足报错
5.不加sudo编译时(即会报错但因权限不足无法全部编译,通过这种办法节省时间查找错误)报错arch/x86/Makefile:129: CONFIG_X86_X32 enabled but no binutils support,查找网上资料后说是缺少binutils支持,检查更新没有问题,之后找到方案在内核配置时选择:
--> Device Drivers 
--> Multiple devices driver support (RAID and LVM)
--> Device mapper support
(这一项改为n)
再次编译后成功。
 

以上是关于通过内核编译法向Linux内核添加系统调用的主要内容,如果未能解决你的问题,请参考以下文章

Linux内核——通过模块动态添加系统调用

Linux内核分析第五周作业

Linux内核中添加系统调用接口简单示例

编译内核及系统调用的坑之make menuconfig

为Linux-3.10.1内核添加系统调用

Linux 增加系统调用 (转)