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

如何在Kernel >=6.3的内核模块中通过get_free_page分配只读页?

在内核模块(Kernel ≥6.3)中标记页面为只读的可行方案

由于set_memory_ro未导出且kallsyms_lookup禁用,可通过以下两种合规方式实现需求:

方案一:使用导出的set_memory_prot函数

set_memory_prot是内核导出的GPL符号,可直接用于修改内存页的保护属性,适合遵循GPL许可的模块。

代码示例

#include <linux/mm.h>
#include <linux/gfp.h>

void setup_readonly_page(void) {
    // 分配1个物理页(返回内核虚拟地址,已页对齐)
    void *page = get_free_page(GFP_KERNEL);
    if (!page) {
        // 处理分配失败
        return;
    }

    // 将该页设置为只读+不可执行
    int ret = set_memory_prot((unsigned long)page, 1, PAGE_KERNEL_RO);
    if (ret) {
        // 处理设置失败,释放页
        free_page((unsigned long)page);
        return;
    }

    // 后续对page的写入/执行操作会触发页错误
    // ...
}

关键说明

  • PAGE_KERNEL_RO是内核定义的页保护标志,包含「只读」「非执行」属性,恰好满足需求。
  • set_memory_prot会自动处理页表修改、TLB刷新等底层操作,无需手动干预。
  • 该函数要求模块遵循GPL许可(因符号为EXPORT_SYMBOL_GPL导出)。

方案二:直接操作页表(非GPL模块可选)

如果模块无法遵循GPL许可,可直接修改对应页的页表项(PTE),手动设置权限并刷新TLB。

代码示例

#include <linux/mm.h>
#include <linux/gfp.h>
#include <asm/pgtable.h>

void setup_readonly_page(void) {
    void *page = get_free_page(GFP_KERNEL);
    if (!page) {
        return;
    }

    // 获取内核虚拟地址对应的页表项(PTE)
    pte_t *pte = virt_to_kpte(page);
    if (!pte) {
        free_page((unsigned long)page);
        return;
    }

    // 清除页表项的「可写」和「可执行」位
    pgprot_t new_prot = __pgprot(pte_val(*pte) & ~(_PAGE_RW | _PAGE_X));
    // 更新页表项
    set_pte_at(&init_mm, (unsigned long)page, pte, pte_modify(*pte, new_prot));
    // 刷新TLB,确保权限变更生效
    flush_tlb_kernel_range((unsigned long)page, (unsigned long)page + PAGE_SIZE);

    // 后续对page的写入/执行操作会触发页错误
    // ...
}

关键说明

  • virt_to_kpte是x86架构特有的函数,用于获取内核虚拟地址对应的PTE指针。
  • 修改页表后必须调用flush_tlb_kernel_range刷新TLB,否则CPU可能仍使用旧的权限缓存。
  • 此方法需注意页表层级:get_free_page分配的是4KB普通页,操作PTE层级即可;若使用大页,需调整为操作PMD/PUD项。

注意事项

  • 页面设置为只读后,内核自身对该页的写入操作会触发页错误,需确保后续逻辑不会意外写入;若需临时写入,可先调用set_memory_prot改回PAGE_KERNEL,操作完成后再恢复只读。
  • 分配的页使用完毕后,需调用free_page释放,释放前建议先恢复可写权限(避免释放时内核操作页表出错)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 07:35:28