简单的修改IDT,实现hook page_fault中断处理进程

一个想法的副产物,,,

参考

http://stackoverflow.com/questions/2497919/changing-the-interrupt-descriptor-table

不多说 就上代码算了。。。

Centos 5.5 编译测试通过

#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/desc.h>

typedef struct desc_struct gate_desc;

struct desc_easy {
	unsigned short a;
	unsigned short b;
	unsigned short c;
	unsigned short d;
} __attribute__((packed)) ;

struct desc_ptr {
        unsigned short size;
        unsigned long address;
} __attribute__((packed)) ;

#define PGFAULT_INT 0x0E

static unsigned long isr_orig;
static unsigned long isr_new;
static gate_desc *PF_gate;

asmlinkage void my_function(void);

void stub(void)
{
	__asm__
	(
	"		pushal 				\n"
	"		pushl %es			\n"
	"		pushl %ds			\n"
	"       call my_function    \n"
	"       popl %ds            \n"
	"       popl %es            \n"
	"       popal               \n"
	"       jmp  *isr_orig      \n"
	);
}

asmlinkage void my_function(void)
{
	unsigned long add;
	asm("movl %%cr2,%0":"=r"(add));
	printk("PID: %d >> %08x\n",current->tgid,(unsigned int )add);
}

int pgfault_init( void )
{
	struct desc_ptr idtr;
    gate_desc *idt_table;

    printk("+z+ pgfault_init\n");
    //获取IDT指针
    asm ("sidt %0" : "=m" (idtr));

    //page_fault_gate地址
    idt_table = ((gate_desc *) idtr.address);
    PF_gate = &idt_table[PGFAULT_INT];

    //保存原始的page_fault()地址
    isr_orig = (PF_gate->a & 0xffff) | (PF_gate->b & 0xffff0000);

    //把新的处理函数地址填充进去
    isr_new = (unsigned long)&stub;
    ((struct desc_easy *) PF_gate)->a = (unsigned short) (isr_new & 0x0000FFFF);
    ((struct desc_easy *) PF_gate)->d = (unsigned short) (isr_new >> 16);

    return 0;
}


void pgfault_exit( void )
{
	printk("+z+ pgfault_exit\n");
	//还原以前的page_fault地址
	((struct desc_easy *) PF_gate)->a = (unsigned short) (isr_orig & 0x0000FFFF);
	((struct desc_easy *) PF_gate)->d = (unsigned short) (isr_orig >> 16);
}

MODULE_LICENSE("GPL");
module_init( pgfault_init);
module_exit( pgfault_exit);



你可能感兴趣的:(简单的修改IDT,实现hook page_fault中断处理进程)