英语

页表检查

简介

页表检查允许通过确保防止某些类型的内存损坏来加强内核。

页表检查在新的页面通过将其页表条目 (PTEs PMDs 等) 添加到表中从而可以从用户空间访问时执行额外的验证。

在检测到大多数损坏的情况下,内核会崩溃。页表检查会带来少量的性能和内存开销。因此,默认情况下它是禁用的,但可以在额外加固比性能成本更重要的系统上选择启用。此外,由于页表检查是同步的,它可以通过在错误映射发生时崩溃内核来帮助调试双重映射内存损坏问题,而不是像内存损坏错误那样通常发生的那样稍后崩溃。

它还可以用于对各种标志进行页表条目检查,并在检测到非法条目标志组合时转储警告。目前,userfaultfd 是唯一使用此类方法来对 wr-protect 位针对任何可写标志进行健全性检查的用户。在这种情况下,非法标志组合不会直接导致数据损坏,但会导致只读数据可写,从而在稍后修改页面内容时导致损坏。

双重映射检测逻辑

当前映射

新映射

权限

规则

匿名

匿名

读取

允许

匿名

匿名

读取 / 写入

禁止

匿名

命名

任何

禁止

命名

匿名

任何

禁止

命名

命名

任何

允许

启用页表检查

使用以下方式构建内核

  • PAGE_TABLE_CHECK=y 注意,它只能在 ARCH_SUPPORTS_PAGE_TABLE_CHECK 可用的平台上启用。

  • 使用 'page_table_check=on' 内核参数启动。

可选地,使用 PAGE_TABLE_CHECK_ENFORCED 构建内核,以便在没有额外内核参数的情况下支持页表。

实现说明

我们特意决定不使用 VMA 信息,以避免依赖 MM 状态 (除了有限的 “struct page” 信息)。页表检查是独立于 Linux-MM 状态机的,它验证用户可访问的页面是否没有被错误地共享。

PAGE_TABLE_CHECK 依赖于 EXCLUSIVE_SYSTEM_RAM。原因是,如果没有 EXCLUSIVE_SYSTEM_RAM,则允许用户通过 /dev/mem 将任意物理内存区域映射到用户空间。与此同时,页面可能会在仍在用户空间中映射时更改其属性 (例如,从匿名页面更改为命名页面),从而导致页表检查检测到“损坏”。

即使使用 EXCLUSIVE_SYSTEM_RAM,仍然可能允许通过 /dev/mem 映射 I/O 页面。但是,这些页面始终被视为命名页面,因此它们不会破坏页表检查中使用的逻辑。