title: What is the error of "linux unable to handle kernel paging request at ffffffff00000010"?
body: <p>I have written some Linux kernel code, which causes runtime error, and reports <code>linux unable to handle kernel paging request at ffffffff00000010</code>.</p>
  
  <p>It is just a code to hook the <code>open</code> system call in Linux kernel programming.</p>
  
  <p>The code is listed below:</p>
  
  <pre><code>#include &lt;linux/kernel.h&gt;
  #include &lt;linux/init.h&gt;
  #include &lt;linux/module.h&gt;
  #include &lt;asm/uaccess.h&gt;
  #include &lt;asm/fcntl.h&gt;
  #include &lt;asm/unistd.h&gt;
  #include &lt;asm/ia32_unistd.h&gt;
  #include &lt;asm/msr.h&gt;
  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 &amp;= 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 &lt; needle_len, 0)){ 
          return NULL;
      }
      for (begin = (const char *) haystack; begin &lt;= last_possible; ++begin) 
      { 
          if (begin[0] == ((const char *) needle)[0] 
              &amp;&amp; !memcmp((const void *) &amp;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("xxx@yyy.com");
  </code></pre>