模块添加syscall
在《添加一个syscall》一文中需要修改内核源码和重新编译安装内核才能添加自己的系统调用,这太浪费时间了,调试也很不方便,这次准备实现一个内核模块来添加syscall,这样就不再需要漫长的等待了。 一旦内核编译完成后,其系统调用表大小已确定下来,如果在其后追加,很容易造成内存溢出问题,故而这里只是替换《添加一个syscall》里的314号新增系统调用,既然要替换,那么先要获得系统调用表的起始位置,可由如下方法获得: 1.编译后的Linux源码目录下的System.map文件; 2./proc/kallsyms; 3./boot/System.map-3.13.6 (具体对应自己的版本,我的是3.13.6); 在上面任一文件搜索sys_call_table,即可得到系统调用表的入口位置: ffffffff818013c0 R sys_call_table 其中, ffffffff818013c0是64位系统对应的系统调用表入口(我机器上的),R表示该地址是只读的,我们肯定是没有写的权限了,但是Intel的相关手册里有说到CR0(控制寄存器0)的bit 16(第17位)是写保护标志,当该位置位(为1)时只读,清零(为0)时则可读写,那我们玩一个花样就是在修改314号系统调用对应的处理函数时,让bit16为0,改好后恢复原来值,卸载模块时修改314号系统调用为原来对应的函数,这里面会用到内核源码里的宏X86_CR0_WP和read_cr0()以及write_cr0()两函数,均在源码里有注明,模块源码如下: #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h> #include <linux/unistd.h> #include <linux/time.h> #include <asm/uaccess.h> #include <linux/sched.h> #include <uapi/asm/processor-flags.h> //X86_CR0_WP #include <asm/special_insns.h> //read_cr0(),writ...