ARM TrustZone:从安全监视器运行时服务访问非安全缓冲区

ARM TrustZone: Accessing a non-secure buffer from a secure monitor runtime service

我的设置包括一个 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(显然)崩溃了。如果有人可以帮助我填写剩余的必需步骤以获得有效参考,将不胜感激。

The problem I'm facing is that I can't find any information on what steps are required in order to translate the virtual address from the Linux Kernel at NS:EL1 to the translation regime of 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 TrustZone,