Linux安装系统调用表更改模块时系统崩溃(unable to handle kernel paging request at XX)

安装内核模块时,如果里面有更改系统调用等情况,有时会崩溃,出现如下错误:

<1>BUG:unable to handle kernel paging request at virtual address c06357b4
printing eip:d0aac056 *pde = 0e9dd163 *pte = 00635161 

Oops: 0003 [#1] SMP 
Modules linked in: test2(U) addsym(U) nls_utf8autofs4 fuse rfcomm l2cap bluetooth sunrpc nf_conntrack_ftp nf_conntrack_ipv4xt_state nf_conntrack xt_tcpudp ipt_REJECT ip

 

原因:由于控制寄存器CR0的第16位若置位,则表示禁止系统进程写只有只读权限的页面(sys_call_table),

所以我们给sys_call_table添加内容的话就必须将CR0的第16位清零,在模块卸载的时候给还原

示例代码如下:

清除标志位:

static int clear_cr0(void)

{

    unsigned int cr0 = 0;

    unsigned int ret;

   

    asm volatile ("movq %%cr0, %%rax":"=a"(cr0));

    ret = cr0;

    cr0 &=0xfffeffff;

    asm volatile ("movq %%rax, %%cr0": :"a"(cr0));

 

    return ret;

 

}

恢复标志位:

static void setback_cr0(int val)

{

    asm volatile ("movq  %%rax,  %%cr0": :"a"(val));

   

}

 

注意:

在32位和64位的系统下汇编指令是有区别的,上面是32位系统下的代码,

从32位扩充到了64位,名字也发生了变化。8个通用寄存器(eax, ebx,ecx, edx, ebp, esp, esi, edi)在新的结构中被命名为rax,rbx, rcx, rdx, rbp, rsp, rsi, rdi。movl命令也需相应改成movq。

 

使用示例:

    orig_cr0= clear_cr0();//保留标志位

    sys_call_table[__NR_connect]= (unsigned long )test;//更改系统调用

    setback_cr0(orig_cr0);//恢复标志位

当卸载模块,需要恢复系统调用时,同理。

你可能感兴趣的:(Linux安装系统调用表更改模块时系统崩溃(unable to handle kernel paging request at XX))