系统调用和快速系统调用

欢迎访问小站,阅读原文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");

屏幕截图_060313_070553_PM

获取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

待续。。。



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值