Hacker News 中文摘要

RSS订阅

Linux内部机制:/proc/self/mem如何写入不可写内存(2021) -- Linux Internals: How /proc/self/mem writes to unwritable memory (2021)

文章摘要

Linux系统中/proc/self/mem文件具有特殊写入特性:即使目标内存被标记为不可写,通过该文件的写入操作仍能成功。这种"穿透"设计被Julia JIT编译器和rr调试器等工具实际应用,反映了操作系统内核可以绕过硬件内存保护机制的特殊能力,展现了系统内核与硬件权限控制的微妙关系。

文章总结

标题:Linux内核探秘:/proc/self/mem如何写入不可写内存

文章核心内容:

  1. 特殊现象揭示
  • /proc/*/mem伪文件具有"穿透写入"特性,即使目标虚拟内存标记为不可写,仍能成功写入
  • 该特性被Julia JIT编译器和rr调试器等项目实际应用
  1. 技术验证实验
  • 通过C++代码演示如何修改只读内存页和libc代码段
  • 成功将0x41414140写入只读内存并验证读取
  • 通过写入0xCC触发SIGTRAP信号,证实成功修改libc的getchar函数
  1. 硬件机制分析
  • x86-64通过CR0.WP(写保护位)和CR4.SMAP(管理模式访问防护)控制内核内存访问
  • CR0.WP默认允许内核写入只读页,而SMAP完全禁用内核访问用户空间内存
  • 实际系统启动时CR0.WP被启用,但内核可通过故障处理绕过限制
  1. 内核实现原理
  • /proc/*/mem通过三层机制绕过MMU限制: a) 使用getuserpagesremote()进行物理帧查找(配合FOLLFORCE标志忽略写保护) b) 通过kmap()将物理帧映射到内核可写地址空间 c) 调用copytouser_page()执行实际写入操作
  • 整个过程巧妙规避了CR0.WP限制,直接操作物理内存
  1. 关键认知突破
  • 内存权限与虚拟地址绑定,而非物理内存本身
  • 内核通过完全掌控虚拟内存系统,可自由重映射物理内存
  • CPU提供的保护机制实际只能构成表面约束
  1. 行业影响
  • 该技术被多个安全研究和漏洞分析引用,包括Dirty Cow漏洞分析等
  • 揭示了操作系统与硬件间的微妙关系,展现内核绕过硬件限制的能力

文章通过具体代码示例、硬件原理分析和内核实现解读,系统性地阐释了这个看似违反内存保护机制的特性背后的技术原理,最终得出"CPU对内核的限制只是表面约束"的重要结论。

评论总结

这篇讨论围绕Linux内核如何绕过内存保护机制访问内存展开,主要观点如下:

  1. 内核绕过内存保护的能力
  • 支持观点:内核拥有页表控制权,总能找到访问方法(评论1:"The kernel owns the page tables. It can always find another way in.")
  • 技术细节:通过/proc/self/mem写入时,内核会绕过MMU进行软件模拟(评论3:"the kernel bypasses the MMU...allows it to disregard any memory protection")
  1. CPU内存保护机制的复杂性
  • 技术补充:x86-64有多种内存保护设置,包括Memory Protection Keys、虚拟化NPT/EPT表等(评论2:"There are a couple more than two...SEV and SGX also have their own ways")
  • 特殊案例:TDX模块等特殊物理地址范围也受保护(评论2:"the TDX module's range. You can't write there")
  1. 实现细节讨论
  • 权限检查:代码仍会检查VMMAYWRITE标志(评论5:"it does still check VMMAYWRITE")
  • 历史背景:Linus曾试图修改这个行为(评论4:"I'm still surprised I was the first one to notice")
  1. 文件系统批评
  • 对比观点:Linux的/proc是对Plan9的拙劣模仿(评论6:"/proc it's a bad imitation of plan9's /proc")