Unable to handle kernel NULL pointer when using cpuid instruction in kernel module for linux kernel 2.6.5

From: Lora Yin (HangZhou)
Date: Mon Apr 12 2004 - 21:26:35 EST


Hi,
I write a kernel module to test cpuid instruction in a kernel module.
In the module if I push the registers before calling the cpuid instruction
and pop them after calling, install the module will cause a system error
In the module if I do not pushl/popl the registers, install the module will
be successful.
I have test the module in the Redhat 9.0 with linux kernel 2.4.20-8, but in
this version the error is not exist.
Does anyone know if there is any special difference between the two version
of linux kernel which will affect the execution of asm instruction such as
cpuid?

Thanks.
Best regards,
Lora

The error message is as following:

test: module license 'unspecified' taints kernel.
check_ace = 0
Unable to handle kernel NULL pointer dereference at virtual address
00000001
printing eip:
c012fd02
*pde = 00000000
Oops: 0002 [#1]
CPU: 0
EIP: 0060:[<c012fd02>] Tainted: P
EFLAGS: 00010246 (2.6.5)
EIP is at sys_init_module+0x122/0x1e0
eax: 00000000 ebx: 00000000 ecx: c030d2f8 edx: c030aa38
esi: c030d2f8 edi: 00000001 ebp: c9f96000 esp: c9f97fa8
ds: 007b es: 007b ss: 0068
Process insmod (pid: 2313, threadinfo=c9f96000 task=c9f8b260)
Stack: c03bfbc4 00000001 ce821380 0804b060 0804b975 bffffc32
c0108b59 0804b060
00000915 0804b050 0804b975 bffffc32 bffffad8 00000080
0000007b 0000007b
00000080 ffffe410 00000073 00000246 bffffa90 0000007b
Call Trace:
[<c0108b59>] sysenter_past_esp+0x52/0x79
Code: c7 07 00 00 00 00 ff 8f a0 00 00 00 8b 47 6c 89 3c 24 89 44




The source code of the module is as following:

//#define MODULE
#include <linux/module.h>
#include <linux/config.h>
#include <linux/init.h>

#define true 1
#define NEH_PUSHREG asm volatile ("pushl %eax\n pushl %ebx\n pushl
%ecx\n pushl %edx\n pushl %esi\n pushl %edi\n")
#define NEH_POPREG asm volatile ("popl %edi\n popl %esi\n popl %edx\n popl
%ecx\n popl %ebx\n popl %eax\n")

static int check_ace(void)
{
int result = 0;
// ?? if use pushl/popl, will be error, why?
NEH_PUSHREG;
asm volatile ("movl $0xC0000000, %%eax\n \
cpuid\n \
cmpl $0xC0000001, %%eax\n \
jnz local_label\n \
cpuid\n \
andl $0xC0, %%edx\n \
jz local_label\n \
movl %1, %0 \n \
local_label:\n"
:"=m"(result)
:"i"(true));
NEH_POPREG;
return result;
}
static int __init init(void){
int result = 0;
result = check_ace();
printk("check_ace = %d\n",result);
if (result != 0){
printk("has ace!\n");
}
return 0;
}
static void __exit fini(void) {
printk("exit\n");
}
module_init(init);
module_exit(fini);


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/