What is the error of "linux unable to handle kernel paging request at ffffffff00000010"?

34,863

It means that somewhere in your code you have an invalid pointer that you are trying to access. I cannot debug your code on the fly but I can give you some suggestions:

  • try to avoid casting until is strictly necessary
  • when you are casting to a pointer, double check that it is what you want to do
  • in the error message there is also the stack, take a look at it in order to identify where is the error
  • you can simply put some printk("%p", pointer) in your code to check the content of your variables. Alternatively, you can use systemtap or similar tools.
Share:
34,863

Related videos on Youtube

Victor
Author by

Victor

I am a Network Software Engineer at Family Zone Cyber Safety. I like computer programming, and I am good at C++, Go, Python, PHP. I have seven years of experience in computer programming.

Updated on November 22, 2020

Comments

  • Victor
    Victor over 3 years

    I have written some Linux kernel code, which causes runtime error, and reports linux unable to handle kernel paging request at ffffffff00000010.

    It is just a code to hook the open system call in Linux kernel programming.

    The code is listed below:

    #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]");