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

Linux x86内核lookup_address在特定页错误场景返回NULL的疑问

问题描述

我在通用v6.1版本Linux内核的arch/x86/mm/fault.c中实现了一个简单的钩子函数is_read_only,该函数通过lookup_address获取虚拟地址对应的页表项(PTE)并判断页面属性。我将此函数调用置于__bad_area_nosemaphore函数内show_signal_msg调用的下方,传入页错误的虚拟地址作为参数。

测试时使用经典Linux页错误/段错误场景:在用户态程序中修改只读字符串,触发错误码为7的页错误,系统日志显示对应信息。根据Intel手册,错误码7表示页存在、处于用户态、操作是写入,但此时lookup_address却返回NULL,明明错误码指示页存在,为何无法正确返回页表项?

原因与解决方案

核心问题:lookup_address的作用范围

lookup_address是专门用于查找内核虚拟地址页表项的函数,它默认遍历的是内核全局页表(init_mm对应的页表),而你传入的是用户态虚拟地址,该地址属于当前进程的用户地址空间,不在内核页表的映射范围内,因此函数返回NULL。

正确的用户态地址页表项查找方式

要获取用户态虚拟地址对应的PTE,需要针对当前进程的用户地址空间操作:

  • 使用get_user_pages_fast:该函数可以快速获取用户虚拟地址对应的物理页,调用成功则说明页表项存在,同时可通过返回的struct page判断页面属性。
  • 手动遍历用户页表:通过current->mm获取当前进程的地址空间结构,从PGD开始逐层解析到PTE,注意操作时需要持有mmap_sem锁,避免页表被并发修改。

补充说明

错误码7是CPU硬件给出的判断,针对的是当前进程用户地址空间中的页表项;而lookup_address不处理用户地址空间,所以两者的判断不存在矛盾。在__bad_area_nosemaphore函数中,当前处于进程上下文,可以安全访问current->mm来操作用户页表。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 14:14:54