You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

内核模块函数迁移触发页错误,如何添加函数读权限?

内核模块函数内存权限问题

问题详情

我编写了如下内核模块代码:

void make_function_writable(void *addr) {
  unsigned int cr0_register;

  asm volatile("mov %%cr0, %0" : "=r"(cr0_register));

  cr0_register &= ~(1 << 16);

  asm volatile("mov %0, %%cr0" : : "r"(cr0_register));
}

void modified(void) { printk(KERN_INFO "world\n"); }

void hello(void) { printk(KERN_INFO "Hello\n"); }

static int __init hooker_init(void) {
  void (*modified_addr)(void) = &modified;

  make_function_writable(modified_addr);

  memmove(modified_addr + 3, modified_addr, 0x19);
  printk(KERN_INFO "Move");

  void (*modified_addr_new)(void) = (void (*)(void))(modified_addr + 3);

  (modified_addr_new)();

  return 0;
}

static void __exit hooker_exit(void) { return; }

module_init(hooker_init);
module_exit(hooker_exit);

MODULE_LICENSE("GPL");

运行时触发页面错误:

unable to handle page fault for address: 3cf741d0
supervisor read access in kernel mode
error_code(0x0000) - not-present page

我试过用set_memory_x和set_memory_rw,但新版本内核里这些函数没法用,请问怎么给函数添加读权限?


解决方案

1. 先定位错误根源

触发的页错误核心不是权限问题,而是目标地址对应的页不存在。modified_addr + 3可能落到了未映射的内存区域,或者你设置的拷贝长度0x19不合理,导致访问越界。另外,直接修改CR0寄存器的方法在现代内核(尤其是开启SMAP/SMEP的x86系统)里不安全,也解决不了页表层面的映射问题。

2. 新版本内核的页权限修改方法

放弃直接操作CR0的方式,用内核提供的官方接口:

  • 方法一:使用virt_to_page+set_page_flags
    先把虚拟地址转成物理页,再设置页的读写属性:

    #include <linux/mm.h>
    
    void set_page_rw(void *addr) {
      struct page *page = virt_to_page(addr);
      set_page_flags(page, PG_RW);
    }
    

    注意:仅适用于内核线性地址,且地址对应的页必须存在。

  • 方法二:使用change_page_attr_set(内核5.4+可用)
    批量修改页属性,比直接操作CR0可靠:

    #include <linux/page-flags.h>
    
    int set_virt_addr_rw(void *addr) {
      return change_page_attr_set(virt_to_page(addr), 1, PAGE_KERNEL_RW);
    }
    

3. 修正代码逻辑错误

你的memmove操作存在风险:modified_addr + 3是函数内部偏移3字节的位置,从这里开始拷贝0x19字节可能覆盖后续内存,甚至超出当前函数所在的页,导致访问未映射区域。建议先通过反汇编确认函数的实际长度,再调整拷贝范围;或者换用更安全的函数跳转逻辑。

另外,调用修改后的modified_addr_new前,要确保该地址所在页已正确映射且有执行权限,修改完内存后记得按需恢复页的执行属性。

4. 适配现代内核安全机制

新版本内核普遍开启了**SMAP(Supervisor Mode Access Prevention)和SMEP(Supervisor Mode Execution Prevention)**这类安全特性,直接修改CR0的WP位(第16位)可能被内核拦截,或引发不可预见的问题。必须使用内核官方接口修改页属性,禁止直接操作CR0。


内容的提问来源于stack exchange,提问作者itamarsch

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 06:53:15