ARM 中的 TrustZone 与 Exception Levels

TrustZone

TrustZone 是 ARM 针对消费级的电子设备,设计的一种硬件架构,目的在于为消费电子产品构建一个安全框架从而抵御各种潜在的攻击。TrustZone 将 SoC (System-on-a-Chip) 硬件和软件划分为 Normal world 和 Secure world 两部分。一些敏感操作,例如加解密、生物识别技术、安全认证等,需要在 Secure world 执行,用户操作系统和一般的应用程序在 Normal world 执行。


在这里插入图片描述

下图是 ARM 官网对 TrustZone 的介绍,从宏观角度来看,Rich OS Application Environment(REE)表示用户操作环境,可以运行各种应用,例如电视或手机的用户操作系统;Trusted Execution Envrionment(TEE)表示系统的安全环境,运行Trusted OS,在此基础上执行可信任应用,包括身份验证、授权管理、DRM认证等,这部分隐藏在用户界面背后,独立于用户操作环境,为用户操作环境提供安全服务 1


Exception Levels

ARMv8 将处理器划分为四个特权等级,我们称之为 Exception Levels,是建立在 TrustZone 的基础之上。下图是 EL3 使用 AArch64 时的 ARMv8 安全模型2
在这里插入图片描述

  • EL0:用户空间,一般程序运行在 Normal world,运行在 Secure world 就称之为TA(Trust Application)
  • EL1:操作系统,Guest OS 运行在 Normal world,例如 Linux / Wlnce,Trusted OS 运行在 Secure world,如高通的 QSEE, 开源的 OP-TEE,豌豆荚的 TEE 等
  • EL2:为了支持虚拟化而设计的 Hypervisor 层,只在 Normal world 使用
  • EL3:作为交换通道,Normal world 发送 SMC 指令是通过 Secure Moniter 层,进入到 Secure world 中的,Secure Moniter 的作用是用于 Noraml world 和 Secure world 切换使用。

不同的 EL 对应不同的权限和寄存器,高权限行为不能在低权限 EL 上执行。常见的安全方式有两种:横向越权,即从 None-secure state 执行 Secure state 的应用或系统;纵向越权,即从低权限 EL 执行 高权限 EL 的行为。


Android 调用内核接口

我们以 Android 为例,EL0 的应用程序想要调用 EL1 的代码(内核代码),一般通过中断,就可以让内核进入异常向量表。异常向量表是 ARM 架构中常用的概念,应用程序通过系统调用访问内核,系统调用要通过软中断来实现。

异常中断类型

异常类型 : ARM 架构 支持 七种类型的异常[^3]

  • Reset : 处理器在工作时, 突然 按下重启键, 就会触发该异常
  • Undefined instructions : 处理器无法识别指令的异常, 处理器执行的指令是有规范的, 如果 尝试执行 不符合要求的指令, 就会进入到该异常指令对应的地址中
  • Software interrupt (SWI) : 软中断, 软件中需要去打断处理器工作, 可以使用软中断来执行
  • Prefetch Abort (instruction fetch memory abort) : 预取指令失败, ARM 在执行指令的过程中, 要先去预取指令准备执行, 如果预取指令失败, 就会产生该异常
  • Data Abort (data access memory abort) : 读取数据失败
  • IRQ (interrupt) : 普通中断
  • FIQ (fast interrupt) : 快速中断, 快速中断要比普通中断响应速度要快一些

下图来自官网的说明
在这里插入图片描述

异常处理

在 ARM 嵌入式编程中,通过编写异常向量表(ARM 汇编代码)、链接器就可以形成我们自己的异常处理。建立异常向量表->进栈保存现场->处理异常->出栈恢复现场。
在这里插入图片描述

调用内核接口

调用内核接口需用从 EL0 到 EL1,一般分为以下过程

  • 通过中断,进入异常向量表
  • 找到系统调用号,并进入不同的系统调用
  • 通过系统调用和虚拟文件系统,调用各种驱动代码

libc 是我们常用的库(glibc 是 GNU 发布的 libc 库,即 c 运行库。glibc 是 linux 系统中最底层的 api,几乎其它任何运行库都会依赖于glibc)
在这里插入图片描述

libc 库已经封装好了中断代码,所有需要调用内核代码的 API(例如 read/write/fork/ioctl )都会调用 DO_CALL 宏,这个宏在多处都有定义。

扫描二维码关注公众号,回复: 10733947 查看本文章

关于内核调用函数的详细调用,请访问下一篇博客。


总结

作为业余爱好者,而不是开发人员,我们并没有详细研究 TrustZone 的硬件实现机制,从安全角度来说,大体了解其概念即可知道 Exception Levels 的基础,方便后续我们对 Linux 内核、驱动、系统调用的研究。


  1. https://blog.csdn.net/guyongqiangx/article/details/78020257 ↩︎

  2. https://developer.arm.com/docs/100095/0002/programmers-model/armv8-a-architecture-concepts/exception-levels ↩︎

发布了52 篇原创文章 · 获赞 30 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/song_lee/article/details/105152161
今日推荐