基于Armv9 CPU的手机芯片已经被广泛采用。如何在Android用上Armv9 CPU新引入的PAC,BTI, MTE安全特性和SVE2呢?
早在2020年,arm已经和google合作将这些新特性带入到Android 12, NDK r23也支持了PAC, BTI等。
1. 如何利用PAC, BTI 功能
a. Linux kernel
需要使用linux v5.10及以后的支持PAC,BTI的版本:
Kernel配置需要使能CONFIG_ARM64_PTR_AUTH=y, 这使能了user space的PAC支持。如果要使能kernel代码本身的PAC保护,需要使能ARM64_PTR_AUTH_KERNEL =y。
BTI的支持类似,需要使能CONFIG_ARM64_BTI和CONFIG_ARM64_BTI_KERNEL。
还需要支持PAC和BTI的GCC编译器。
因为Kernel可使用软件随机数来产生PAC的key, 支持PAC不需要SoC层面的支持。BTI的影响纯粹在CPU层面,更不需要SoC层面的支持。使能PAC和BTI非常便捷。
b. AOSP
需要在创建的device的makefile device/<company-name>/<device-name>/ boardconfig.mk 选择合适的 TARGET_ARCH_VARIANT,如果要利用上PAC,BTI,需要设置TARGET_ARCH_VARIANT := armv8-a-branchprot
这样编译AOSP时,https://android.googlesource....
会选择NDK LLVM编译的选项为-mbranch-protection=standard, 此选项会让编译器编译出带PAC和BTI指令的库,可执行性文件。
如果通过llvm-readelf查看编译后的目标文件,可以看到这样的属性:
Properties: aarch64 feature: BTI, PAC
c. 自有native程序,库
需要在项目对应的编译选项在加上
-mbranch-protection=standard
2.如何利用MTE
a. 硬件平台要求
- 支持MTE的CPU
- 支持MTE transaction的总线接口,如CHI-E总线
- 支持MTE的互联(Interconnect),如CI-700(用来解释分拆MTE transaction,将MTE translation转换为对DRAM里用来存储MTE tag的内存区域的一般访问,optionally, CI-700可以有MTE cache来cache MTE tag访问)
b. Firmware的支持
- 使能EL2, EL1, EL0对MTE tag访问
- 如果使用如CI-700的互联,需要配置CI-700寄存器,以告知DRAM中存放MTE tag内存区域的地址信息
c. Linux Kernel
需要使能
CONFIG_ARM64_MTE=y, CONFIG_KASAN=y, CONFIG_KASAN_HW_TAGS=y
使kernel支持user space利用MTE
d. Android的支持
参见Google Android document:
https://source.android.com/do...
- 对应heap-tagging(malloc,free)的支持,scudo库已经通过intrinsics支持,不需要额外的编译命令
external/scudo/standalone/memtag.h
- 对于每个进程是否要使用heap-tagging,使用synch或是async的MTE check模式,可以
a) 对一个项目,可以在Android.bp中
例如在external/iptables/iptables/Android.bp 中
或是Android.mk中
b) 使用product variable对source tree下的子目录
或是
通过llvm-readelf可以看到编译出来的目标文件具有
.note.android.memtag
属性
以上编译配置可以在运行时通过以下系统属性override
arm64.memtag.process.<name> = (off | sync | async)
其中name是可执行文件的名字。
c)设置执行环境变量
MEMTAG_OPTIONS=(off|sync|async)
通过以上环境变量设置之后启动的native应用都按配置做MTE检查
d) 通过AndroidManifest.xml
通过AndroidManifest.xml下的<application> 或 <process>,设置
android:memtagMode=(off|default|sync|async)
例如在packages/modules/Bluetooth/android/app/AndroidManifest.xml中
e) 运行时设置
开发者可以通过调用
int mallopt(M_BIONIC_SET_HEAP_TAGGING_LEVEL, level)
动态控制MTE模式,level可以是
● M_HEAP_TAGGING_LEVEL_NONE
● M_HEAP_TAGGING_LEVEL_ASYNC
● M_HEAP_TAGGING_LEVEL_SYNC
为Android image编译提供MTE的支持
Google强烈建议在开发阶段为所有的native二进制使能MTE sync check, 可以通过设置环境变量SANITIZE_TARGET=memtag_heap SANITIZE_TARGET_DIAG=memtag_heap m
这使除zygote64之外的native应用对进行MTE check.
在build/make/core/config_sanitizers.mk中
3. 如何利用SVE2
a. Linux Kernel
需要使能CONFIG_ARM64_SVE=y, kernel本身不利用SVE,主要是save/restore SVE寄存器context, 并通过auxv HWCAP/HWCAP2告诉user space平台对SVE的支持。
b. AOSP
目前阶段AOSP项目本身还未使用SVE2,SVE2的优化还在持续进行中。
c. 自有应用/库
可以利用SVE2 intrinsics或内嵌汇编优化,并在项目编译选项中加入-march= … +sve2
比如arm compute library就已经有SVE/SVE2的支持,
https://github.com/ARM-softwa...