如何在 Linux 中禁止访问物理内存?

如何在 Linux 中禁止访问物理内存?

我使用嵌入式系统(来自 Xilinx 的 Zynq。它使用 ARMv7、Cortex-A9)并运行 Linux。我需要确保不访问某个特定的物理内存范围曾经由内核空间或用户意外创建。我可以发出信号、数据中止或其他任何东西,但硬件尝试一定不比MMU走得更远。

在裸机模式和 U-Boot 中,我可以直接访问 TLB 的位置,并且可以通过将 MMU 配置为在发生任何读或写访问时数据中止来限制硬件级别的内存访问。我想在 Linux 中执行此操作,即使 mmap() 也会引发数据中止。

推理:

在 Zynq 中,2GB 地址空间被分配给以下范围:可能永远不会在硬件级别上做出响应。 ARM 的 AXI/AMBA 协议规定,主机永远不会“放弃”访问某个地址的尝试,即使那里什么也没有。如果我取消引用没有硬件驻留的指针,整个芯片就会挂起。

我知道我可以“只是不给 sudo”或“只是编写好的驱动程序”,但这甚至是在该级别之前。我想在早期启动时将 MMU 的 TLB 设置为在我的超级用户执行了一些错误编码时完全中止数据。我宁愿不破解 boot.S,而是直接修改 TLB,然后使用 API 刷新它。

答案1

Linux 内核有选项来限制它将用作 RAM 的物理地址范围,但这并不能阻止有缺陷的驱动程序或通过访问/dev/mem来逃避这些范围。在启动阶段修改 MMU 配置不会带来任何好处,因为无论如何内核都会在启动阶段控制 MMU。如果您想绝对确保 Linux 系统不会访问某些内存范围,则需要一些外部控制。

您的架构提供了一种限制 Linux 内核可以访问的内容的方法:信任区(或更准确地说,TrustZone 加上内存防火墙)1。我怀疑您是否会为您正在做的事情找到交钥匙解决方案,您需要做一些编码。幸运的是,有关 Zync 上 TrustZone 的文档可用。基本思想如下:

  • 处理器以 S 模式启动。设置 TrustZone 控制寄存器以禁用该不良 2GB 范围内的非安全访问。
  • 完成此操作后,切换到 NS 模式并分支到正常引导加载程序。
  • 如果 Linux 尝试访问被阻止的 2GB 范围,则该请求将在到达内存总线之前被阻止,并且会触发中止(如果涉及任何缓存或预取,则为不精确中止)。

最近的 ARM 处理器提供了另一种方法,即运行虚拟机管理程序,但这在 Cortex-A9 上不可用。

相关内容