欢迎访问小站,阅读原文http://www.yandong.org/archives/519
介绍
系统调用,顾名思义,说的是操作系统提供给用户程序调用的一组“特殊”接口。用户程序可以通过这组“特殊”接口来获得操作系统内核提供的服务,比如用户可以通过文件系统相关的调用请求系统打开文件、关闭文件或读写文件,可以通过时钟相关的系统调用获得系统时间或设置定时器等。
从逻辑上来说,系统调用可被看成是一个内核与用户空间程序交互的接口——它好比一个中间人,把用户进程的请求传达给内核,待内核把请求处理完毕后再将处理结果送回给用户空间。
什么是快速系统调用
在产生一个中断(广义的中断,包括硬中断、软中断、异常)后,处理器中控制器会进行一系列权限检查,只有得到核实后,控制单元才设置中断处理所需要的执行环境。基于软中断int 0×80的系统调用同样也需要作一系列的检查,才能进入内核态进行系统调用的处理工作。
由于系统调用的特点,这一系列权限检查变得多余。为此Intel在Pentium II处理器中引入了一对新的指令SYSENTER/SYSEXIT,用于实现快速系统调用;其中指令SYSENTER用于进入内核态,而指令SYSEXIT用于从内核态返回。这两条该指令避免了权限检查,直接将处理器置为预定义的运行级别(基于软中断的系统调用需要从门描述符中获得运行级别信息)。同时,通过将系统调用所需的执行环境信息保存在一组型号相关寄存器(Model Specific Register,简称MSR)中,避免了访问内存,进一步提高进入内核态的速度。下面分小节对快速系统调用进行全面的介绍和分析。
如何检查系统是否支持快速系统调用呢?
static int my_init_module(void) { if (!boot_cpu_has(X86_FEATURE_SEP)) { printk(KERN_ERR "NOT SUPPORT \n"); return 0; } printk(KERN_ERR "SUPPORT \n"); return 0; }
修改linux系统调用
原理: 系统调用都在sys_call_table的表里面,修改这个表里面的东西可以达到修改系统调用的目的,
另外获取sys_call_table地址的一个简单方式是在/boot/system.map里面查找
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/sched.h> #include <linux/init.h> #include <linux/fs.h> #include <linux/file.h> #include <linux/fs_struct.h> #include <linux/fdtable.h> #include <linux/string.h> #include <linux/mm.h> #include <linux/syscalls.h> #include <linux/list.h> #include <linux/jiffies.h> #include <linux/cdev.h> #include <asm/unistd.h> #include <asm/uaccess.h> #include <linux/path.h> #include <linux/time.h> #include <linux/stat.h> #include <net/sock.h> #include <net/inet_sock.h> #include <asm/cpufeature.h> #define MY_FILE "/root/linux_kernel_info" static int my_init_module(void); static void my_cleanup_module(void); unsigned int clear_and_return_cr0(void); void setback_cr0(unsigned int val); unsigned long **sys_call_table = (unsigned long **)0xc0509940; int orig_mkdir; unsigned int orig_cr0; /** * 清除写保护 */ unsigned int clear_and_return_cr0(void) { unsigned int cr0 = 0; unsigned int ret; asm volatile ("movl %%cr0, %%eax" : "=a"(cr0) ); ret = cr0; /* clear the 20 bit of CR0, a.k.a WP bit */ cr0 &= 0xfffeffff; asm volatile ("movl %%eax, %%cr0" : : "a"(cr0) ); return ret; } /** *设置cr0,--本程序用来恢复写保护 */ void setback_cr0(unsigned int val) { asm volatile ("movl %%eax, %%cr0" : : "a"(val) ); } int hacked_mkdir(const char __user *pathname, int mode) { printk(KERN_ALERT "mkdir do nothing\n", MY_FILE); return 0; /*everything is ok, but he new systemcall does nothing*/ } static int my_init_module(void) { printk(KERN_ALERT "sys_call_table %x\n", sys_call_table); orig_mkdir=(int)(sys_call_table[__NR_mkdir]); printk(KERN_ALERT "sys_call_table %x\n", orig_mkdir); orig_cr0 = clear_and_return_cr0(); //清除写保护 sys_call_table[__NR_mkdir]=(void *)hacked_mkdir; setback_cr0(orig_cr0); return 0; } static void my_cleanup_module(void) { printk(KERN_ALERT "Module %s unloaded.\n", MY_FILE); orig_cr0 = clear_and_return_cr0(); sys_call_table[__NR_mkdir]=(void *)orig_mkdir; /*set mkdir syscall to the origal one*/ setback_cr0(orig_cr0); } module_init(my_init_module); module_exit(my_cleanup_module); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Nilushan Silva"); MODULE_DESCRIPTION("task_struct offset Finder");
获取sys_call_table的方式
链接
http://www.ibm.com/developerworks/cn/linux/kernel/l-k26ncpu/
http://book.51cto.com/art/200810/93833.htm
http://blog.csdn.net/misterliwei/article/details/4351592
待续。。。