红联Linux门户
Linux帮助

Linux安装系统调用表更改模块时系统崩溃

发布时间:2016-02-23 16:26:58来源:linux网站作者:szkbsgy

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

<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);//恢复标志位

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


本文永久更新地址:http://www.linuxdiyf.com/linux/18342.html