2014-11-14 9 views
8

Ich habe einen Linux-Kernel-Code geschrieben, der Laufzeitfehler verursacht, und meldet linux unable to handle kernel paging request at ffffffff00000010.Was ist der Fehler von "Linux nicht Kernel-Paging-Anfrage bei ffffffff00000010 zu behandeln"?

Es ist nur ein Code, um den Systemaufruf open in Linux-Kernel-Programmierung zu haken.

Der Code ist unten aufgeführt:

#include <linux/kernel.h> 
#include <linux/init.h> 
#include <linux/module.h> 
#include <asm/uaccess.h> 
#include <asm/fcntl.h> 
#include <asm/unistd.h> 
#include <asm/ia32_unistd.h> 
#include <asm/msr.h> 
unsigned long *sys_table = NULL; 
asmlinkage long (*old_open) (const char __user *filename, int flags, umode_t mode); 
static void *memmem(const void *haystack, size_t haystack_len, 
      const void *needle, size_t needle_len); 
#define dbg(format,args...) \ 
    printk("intercept: function:%s-L%d: "format, __FUNCTION__, __LINE__, ##args); 
asmlinkage long new_open(char *filename, int flags, int mode) 
{ 
    printk("call open()\n"); 
    return old_open (filename, flags, mode); 
} 
unsigned int clear_and_return_cr0(void) 
{ 
    unsigned long cr0 = 0; 
    unsigned long ret; 
    asm volatile ("movq %%cr0, %%rax" 
       : "=a"(cr0) 
      ); 
    ret = cr0; 
    /* clear the 20 bit of CR0, a.k.a WP bit */ 
    cr0 &= 0xfffffffffffeffff; 
    asm volatile ("movq %%rax, %%cr0" 
       : 
       : "a"(cr0) 
      ); 
    return ret; 
} 
void setback_cr0(unsigned long val) 
{ 
    asm volatile ("movq %%rax, %%cr0" 
       : 
       : "a"(val) 
      ); 
} 
static unsigned long get_syscall_table_long(void) 
{ 
    #define OFFSET_SYSCALL 200 
    unsigned long syscall_long, retval; 
    char sc_asm[OFFSET_SYSCALL]; 
    rdmsrl(MSR_LSTAR, syscall_long); 
    memcpy(sc_asm, (char *)syscall_long, OFFSET_SYSCALL); 
    retval = (unsigned long) memmem(sc_asm, OFFSET_SYSCALL, "/xff/x14/xc5", 3); 
    if (retval != 0) { 
     retval = (unsigned long) (* (unsigned long *)(retval+3)); 
    } else { 
     printk("long mode : memmem found nothing, returning NULL:("); 
     retval = 0; 
    } 
    #undef OFFSET_SYSCALL 
    return retval; 
} 
static void *memmem(const void *haystack, size_t haystack_len, 
      const void *needle, size_t needle_len) 
{ 
    const char *begin; 
    const char *const last_possible = (const char *) haystack + haystack_len - needle_len; 
    if (needle_len == 0){ 
     /* The first occurrence of the empty string is deemed to occur at 
      the beginning of the string. */ 
     return (void *) haystack; 
    } 
    if (__builtin_expect(haystack_len < needle_len, 0)){ 
     return NULL; 
    } 
    for (begin = (const char *) haystack; begin <= last_possible; ++begin) 
    { 
     if (begin[0] == ((const char *) needle)[0] 
      && !memcmp((const void *) &begin[1], 
        (const void *) ((const char *) needle + 1), 
        needle_len - 1)){ 
      return (void *) begin; 
     } 
    } 
    return NULL; 
} 
static int init_sys_call_table(void) 
{ 
    printk("init_sys_call_table\n"); 
    unsigned long orig_cr0 = clear_and_return_cr0(); 
    printk("orig_cr0 %lu\n",orig_cr0); 
    sys_table = (unsigned long *) get_syscall_table_long(); 
    if (sys_table == 0){ 
     dbg("sys_table == 0/n"); 
     return -1; 
    } 
    sys_table = (unsigned long)sys_table | 0xffffffff00000000; 
#define REPLACE(x) old_##x = sys_table[__NR_##x];\ 
    sys_table[__NR_##x] = new_##x 
    REPLACE(open); 
    setback_cr0(orig_cr0); 
    return 0; 
} 
static void clean_sys_call_table(void) 
{ 
    unsigned long orig_cr0 = clear_and_return_cr0(); 
#define RESTORE(x) sys_table[__NR_##x] = old_##x 
    RESTORE(open); 
    setback_cr0(orig_cr0); 
    return ; 
} 
static int __init init_64mod(void) 
{ 
    init_sys_call_table(); 
    return 0; 
} 
static void __exit exit_64mod(void) 
{ 
    clean_sys_call_table(); 
} 
module_init(init_64mod); 
module_exit(exit_64mod); 
MODULE_AUTHOR("[email protected]"); 

Antwort

5

Es bedeutet, dass irgendwo in Ihrem Code Sie einen ungültigen Zeiger, die Sie zugreifen möchten. Ich kann Ihren Code on the fly nicht debuggen, aber ich kann Ihnen einige Anregungen geben:

  • Versuch Gießen zu vermeiden, bis dies unbedingt erforderlich ist
  • , wenn Sie auf einen Zeiger Gießen, überprüfen Sie, dass es ist, was Sie wollen Sie gibt
  • in der Fehlermeldung ist auch der Stapel, werfen Sie einen Blick auf sie, um zu ermitteln, wo der Fehler
  • Sie einfach einige printk("%p", pointer) in Ihrem Code setzen können Sie den Inhalt Ihrer Variablen zu überprüfen. Alternativ können Sie systemtap (oder ähnliche Tools) zu
verwenden