用内核模块的方式为系统添加一个系统调用

来源:互联网 发布:软件验收甲方发言稿 编辑:程序博客网 时间:2024/06/07 02:33
今天,利用内核模块的方式向系统添加了一个内核模块。在make后,我开始sudo insmod hello.ko

完成之后。老是出现killed,在lsmod后,发现hello这个模块已经加载上去,但是测试函数调用的时候
,发现根本无法调用这个系统调用。在经过一番分析,查阅资料后,发现是Makefile文件中少了一行
代码,添加上了这行代码后,运行成功。那么,我就和大家分享一下这次的试验。
那么,我们先来了解一下,内核有单体内核和微内核之分。单体内核单体内核整个核心程序都是以
内运行。微内核本身只提供最基本的操作系统的功能,比如进程调度与消息传递等,其他的功能由其
独立的模块提供,每个独立的功能模块都可以是一个进程。当我们需要使用某个功能的时候,我们只
需要在运行的操作系统里安装这个模块,并且运行对应服务,当这个功能不再需要的时候,我们可以
停止这个服务,这样这个功能模块将不占据系统内存和处理器的资源,而不会破坏当前的系统正常运
行。
接下来我们接下来就是我的利用内核模块添加系统调用的试验过程了。首先是要编写生成模块的代
系统调用函数是输入自己的生日,如何出生日期为偶数返回完整的的年月日,否则为0。(下列系统调
用函数代码已省略)

#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/unistd.h>#include <asm/uaccess.h>#include <linux/sched.h>#define my_syscall_num 223//如下的这个值要到你机子上查。cat /proc/kallsyms | grep sys_call_table#define sys_call_table_adress 0xc1511160unsigned int clear_and_return_cr0(void);void setback_cr0(unsigned int val);asmlinkage long sys_mycall(void);int orig_cr0;unsigned long *sys_call_table = 0;static int (*anything_saved)(void);unsigned int clear_and_return_cr0(void){ unsigned int cr0 = 0; unsigned int ret; asm("movl %%cr0, %%eax":"=a"(cr0)); ret = cr0; cr0 &= 0xfffeffff; asm("movl %%eax, %%cr0"::"a"(cr0)); return ret;}void setback_cr0(unsigned int val) //读取val的值到eax寄存器,再将eax寄存器的值放入cr0中{ asm volatile("movl %%eax, %%cr0"::"a"(val));}static int __init init_addsyscall(void){ printk("hello, kernel\n"); sys_call_table = (unsigned long *)sys_call_table_adress;//获取系统调用服务首地址 anything_saved = (int(*)(void)) (sys_call_table[my_syscall_num]);//保存原始系统调用的地址 orig_cr0 = clear_and_return_cr0();//设置cr0可更改 sys_call_table[my_syscall_num] = (unsigned long)&sys_mycall;//更改原始的系统调用服务地址 setback_cr0(orig_cr0);//设置为原始的只读cr0 return 0;}//添加自己的系统调用函数asmlinkage long sys_mycall(void){ //... //... //...}static void __exit exit_addsyscall(void){ //设置cr0中对sys_call_table的更改权限。 orig_cr0 = clear_and_return_cr0();//设置cr0可更改 //恢复原有的中断向量表中的函数指针的值。 sys_call_table[my_syscall_num] = (unsigned long)anything_saved; //恢复原有的cr0的值 setback_cr0(orig_cr0); printk("call exit \n");}module_init(init_addsyscall);module_exit(exit_addsyscall);MODULE_LICENSE("GPL");然后接着编译Makefile文件![Makefi文件](http://img.blog.csdn.net/20161203230607903)之后执行了sudo insmod hello.ko,结果他给我显示了如图![这里写图片描述](http://img.blog.csdn.net/20161203231748323)

但是我查看了一下lsmod,发现加载的模块却正在运行中
这里写图片描述
但是系统调用是是失败的,没有达到预期的返回值。于是在追求原因,发现在Makefile文件下添加
这里写图片描述
之后发现模块运行成功,且没有出现killed情况,最终返回了预期的返回值

0 0
原创粉丝点击