Linux kernel 模块在写入sys调用表时被终止

Linux kernel 模块在写入sys调用表时被终止,linux-kernel,system-calls,Linux Kernel,System Calls,我试图编写一个内核模块来钩住系统读取函数。但是,当我试图将函数指针写入sys call表时,模块就被杀死了。以下是我的初始化函数: int init_module(void) { // set rw/ro functions patch_set_memory_rw = (void *) kallsyms_lookup_name("set_memory_rw"); patch_set_memory_ro = (void *) kallsyms_lookup_name("set_memo

我试图编写一个内核模块来钩住系统读取函数。但是,当我试图将函数指针写入sys call表时,模块就被杀死了。以下是我的初始化函数:

int init_module(void)
{
  // set rw/ro functions
  patch_set_memory_rw = (void *) kallsyms_lookup_name("set_memory_rw");
  patch_set_memory_ro = (void *) kallsyms_lookup_name("set_memory_ro");

  if( patch_set_memory_rw == NULL ||
      patch_set_memory_ro == NULL){
    // something went wrong
    printk(KERN_ALERT "ERROR WITH RW/RO!");
    return 1;
  }
  // Inform that module is staring
  //printk(KERN_INFO "Start Hook Read.");
  syscall_table_pu64 = (void **)kallsyms_lookup_name("sys_call_table");

  //for debugging
  //printk(KERN_ALERT "syscall addr is %llx", syscall_table_pu64);


  // swap read call with own read function
  orig_read_p = syscall_table_pu64[__NR_read];
  // set memory rw to change it
  patch_set_memory_rw((uint64_t)syscall_table_pu64, 1);
  syscall_table_pu64[__NR_read] = own_read_func;
  return 0;
}
错误发生在队列中

syscall_table_pu64[__NR_read] = own_read_func;
有人知道我的问题是什么吗?我想不出来。 错误消息如下所示

RIP: init_module+0x76/0xa0 [hook_read] RSP: ffffa4ad46233c70 RIP:init_模块+0x76/0xa0[hook_read]RSP:ffffa4ad46233c70 及

RIP:0033:0x7f01920bb839
[3476.855557]RSP:002b:00007fffcc925288 EFLAGS:00000246来源:0000000000000139
[3476.857431]RAX:FFFFFFFFFFFFFF DA RBX:0000559daa9f6790 RCX:00007f01920bb839
[3476.858902]RDX:0000000000000000 RSI:0000559daa012c2e RDI:0000000000000003
[3476.860550]RBP:0000559daa012c2e R08:0000000000000000 R09:00007f019238e000
[3476.861959]R10:0000000000000003 R11:0000000000000246 R12:0000000000000000000000
[3476.863399]R13:0000559daa9f6760 R14:0000000000000000 R15:0000000000000000
[3476.864747]代码:89 05 d7 22 00 48 8b 10 48 89 c7 be 01 00 00 48 8b 05 d5 22 00 48 89 b6 22 00 e8 71 3f 26 e2 48 8b 05 b2 22 00 c7 00 00 f0 59 c0 31 c0 5d c3 48 c7 c7 40 00 5a c0 e8 f3 f1

我终于解决了我的问题。为了从syscall中删除写保护,您(当然)可以不使用它的linux系统调用:我花了3个小时才意识到这一点。改用

write_cr0 (read_cr0 () & (~ 0x10000));
启用写和

write_cr0 (read_cr0 () | 0x10000);

使内存再次只读。

系统调用表是只读的。不要试图修改它


如果要挂接读/写操作,则需要选择另一种方式。您可能需要研究的一种机制是系统。

syscall表是只读的,因此您不能更改其值或添加新条目。是的,但我以前禁用了写保护。见下面我的答案。
write_cr0 (read_cr0 () | 0x10000);