1

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

4

1 回答 1

1

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

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

您需要在EL3. 最简单的是有一个平面的virt==phys映射与部分和超部分。

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

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

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

相关:DMA 和 TrustZone访问 TZASC

于 2021-12-01T14:47:50.703 回答