【问题标题】:ARM TrustZone: Accessing a non-secure buffer from a secure monitor runtime serviceARM TrustZone:从安全监视器运行时服务访问非安全缓冲区
【发布时间】:2021-12-01 08:57:58
【问题描述】:

我的设置包含一个 STM32MP157C-DK2,它使用 Trusted Firmware-A 将 SP-MIN 加载为 BL32,将 uBoot+Linux 加载为 BL33。

我正在尝试一个小例子,我从 Linux 内核创建一个 SMC,它传递对非安全内存的引用。处理 SMC 的运行时服务应更改该位置的数据。

我面临的问题是,我找不到任何有关将虚拟地址从 NS:EL1 的 Linux 内核转换为 EL3 的转换机制所需的步骤的任何信息。

我的运行时服务的代码如下所示:

static int32_t my_svc_setup(void)
{
    return 0;
}    

static uintptr_t my_svc_smc_handler(uint32_t smc_fid,
  u_register_t x1,
  u_register_t x2,
  u_register_t x3,
  u_register_t x4,
  void *cookie,
  void *handle,
  u_register_t flags)
{
    uint16_t smc_function_number = (uint16_t) smc_fid;
    uint32_t *data;

    switch(smc_function_number){
    case 123:
        data = (uint32_t *) x1;
        // Address Translation Magic ...
        *data = 42;
        SMC_RET1(handle, 1);
    default:
        SMC_RET1(handle, SMC_UNK);
    }
}

DECLARE_RT_SVC(
    my_svc,
    OEN_OEM_START,
    OEN_OEM_END,
    SMC_TYPE_FAST,
    my_svc_setup,
    my_svc_smc_handler
);

SMC 毫无问题地到达处理程序,但是一旦我尝试取消引用我通过 x1 传递的物理地址,CPU(显然)就会崩溃。如果有人可以帮助我填写剩余的必需步骤以获得有效的参考资料,我们将不胜感激。

【问题讨论】:

  • 我的回答是给出更多的“问题”。您确定您已将物理内存配置为全局可写吗?你有没有在 Linux 中映射过地址;通常由司机完成。您的TZASC 控制器和配置是什么?受信任固件的 EL3 是否完全使用 MMU,如果使用,它是 phys==virt 映射吗?你是如何将这个世界可共享内存传达给 Linux 的?您可以期待有人回答所有这些问题,但如果您能提供答案,则表明需要进行更多研究。
  • 感谢您提出这些问题。我现在无法回答所有这些问题,但仅关键字就能帮助我继续研究。我对整个主题都很陌生,但我仍然不知道一些似乎被视为理所当然的事情。

标签: c arm trust-zone


【解决方案1】:

我面临的问题是,我找不到任何有关将虚拟地址从 NS:EL1 的 Linux 内核转换为 EL3 的转换机制所需的步骤的任何信息。

TrustZone 保护基于物理地址。对于NS:EL1EL3,您可以通过多种方式使用MMU 进行映射,但两者必须映射到相同的物理地址。对于 Linux 内核,您需要添加由物理地址支持的共享内存的映射。您可以使用virt_to_phys() 和这样的映射来查找物理地址。

您需要在EL3 中提供相同的映射。最简单的方法是使用部分和超部分进行平面 virt==phys 映射。

另一部分是您必须设置 TZASC 以将物理部分的权限设置为全球共享。 code manipulating TZASC 的一个例子。这取决于您的硬件,通常这些信息仅在芯片制造商的 NDA 下提供。

另一个警告是您应该将内存映射为不可缓存或依赖刷新,如果系统具有 VIVT,这很容易出错并且可能是安全问题缓存。一些 ARM CPU 具有 VIPT 缓存,并且可能在这些系统上使用缓存内存。

我还建议您不要通过 SMC API 传递地址。您知道固定的世界可共享缓冲区大小。因此,最好传递0..extent-1 的索引,如果地址超出范围,则立即给出错误。这样,只有您的初始 Linux 代码需要创建映射,然后您可以使用给定的虚拟地址并且只传递索引。天真地这似乎更安全。大多数针对 TrustZone 的攻击都针对 API 本身。

相关:DMA and TrustZoneAccessing TZASC

【讨论】:

  • 感谢您的快速回复!只是为了确保我正确理解您:如果 TZASC 为该部分内存正确设置并且 MMU 具有来自 virt 的直接映射,我当前的做事方式(通过 SMC 从 Linux 传递物理地址)将起作用物理?但是更好的方法是在物理内存中创建一个已知的静态区域,将其设置为全球共享并由 Linux 立即分配?
  • 为什么需要使用不可缓存? TrustZone 感知缓存在缓存标记中包含安全状态,不是吗?
  • @solidpixel 有时,缓存条目仅适用于普通世界。即,当安全世界访问时,它要么是安全世界缓存,要么是物理设备,而不是普通世界缓存值。缓存显然带有 NS 标记,或者正常世界实际上可以为安全世界设置别名并尝试检查值。在我看来,最好让它不缓存。
  • @TNTea 你是对的。 TZASC 允许普通世界访问它的问题在于它可以映射整个安全世界并覆盖它。所以通常情况下,安全启动会设置一个固定的物理缓冲区,并且会被“启动锁定”。即,即使有人获得了对 TZASC 寄存器的访问权限,除了完全系统复位之外,它也不能更改。允许动态 TZASC 是一个兔子洞。从理论上讲,您的建议可以工作,但我只建议这样做是为了开发而不是为了真正的部署。这可能是真实设备中的安全风险。
  • 安全世界可以直接访问非安全缓存行——访问类型(S或NS)是内存的安全世界页表条目的一部分(页表中的NS位显然是对于普通页表被忽略并强制为非安全)。
猜你喜欢
  • 2015-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-30
  • 2016-12-27
  • 2015-03-01
  • 1970-01-01
  • 2013-06-11
相关资源
最近更新 更多