安卓生态系统一直在持续改进系统安全。2019年8月,谷歌官方正式宣布在和Arm紧密合作以进一步设计完善 MTE。
常规而言,C和C++属于非内存安全程序设计语言,内存安全缺陷也因此在这两种语言中很常见。而众所周知,Android系统平台是构建在基于C/C++的 native 代码和 Linux 内核代码之上的。因此,内存安全缺陷在安卓系统平台上无可避免的存在着。在Android 9 (Android P) 中,内存安全缺陷占了其高危安全漏洞的半数以上。更令人苦恼的是,内存安全故障表现为非常难以诊断或者调试的可靠性问题,包括偶发式的系统死机或者悄无声息的数据丢失或破坏。所有这一切,都降低了用户满意度并且增加了软件开发的成本。
Android 安全缺陷的原因比例分布
内存访问错误类型
访问错误
- 缓冲区溢出
- 缓冲区恶意读
- 竞争
- 无效的缺页中断
- 内存释放后继续使用
未初始化变量
- 空指针引用
- 野指针
内存泄漏
- 栈耗尽
- 堆耗尽
- 多次内存释放
- 无效的内存释放
- 内存分配/释放不匹配
Android曾经的努力
为了缓解内存安全故障,业界其实已经做了大量的研究,开发了一些相应的技术。最典型的莫过于 ASAN 和 HWASAN,但是这些技术在现有硬件系统上的开销都非常大。
ASAN 是 Address Sanitizer 的简称,也有被写成 ASan的。它是一个针对 native code 的、基于编译器的快速检测工具,可以用来发现软件设计方面的内存缺陷。ASAN可用于检测这么几类错误:
- 栈和堆缓冲区的溢出
- 在堆内存被释放之后继续使用该堆内存
- 在栈内存对象作用域之外,仍然使用该内存
- 对内存对象进行多次释放内存操作
Android Q 及以后的版本,针对Arm AArch64 架构提供了 HWASAN (Hardware-Accelerated ASAN)。HWASAN在 ASAN的基础上,提供新的检测机制:
- 在函数返回后继续使用函数栈内存
整体而言,ASAN已经被 Arm 处理器的 32-bit / 64-bit 模式所支持,同时也被 x86 / x86-64 模式所支持。
通常,带有ASAN特性的软件对于处理器计算能力的消耗,大约是不带有ASAN特性的相同软件对于处理器计算能力的消耗多两倍。前者对于可执行代码空间大小占用的比例,大约比后者代码占用大小额外增加 50% ~ 200%。因此,这个性能开销是相当可观的。
HWASAN 对于处理器和代码大小的额外开销,和 ASAN类似。但是 HWASAN 有着非常小的 额外 RAM 开销, 大约是15%. 因为没有ASAN的一些特殊限制,HWASAN 对内存故障的检测不受限于内存溢出的大小、内存被释放的时间久远等因素。
延伸阅读: HWASAN 的设计文档
MTE在Android的应用
作为一个硬件特性,MTE在被使能以后能够缓解内存安全故障并且只有很小的额外开销。MTE有两种运行模式:
- 精确模式: 提供所有内存违例的更详细信息,相对较大的额外开销
- 非精确模式:提供相对较少的内存违例信息,但是具有更少的处理器额外开销,适合于被一直使能
Android 希望能够从至少三个方面利用MTE特性。
- MTE提供了 对ASAN/HWASAN的兼容支持,因此便于在实验室环境中进行压力测试或灰度测试。因此,将比以前更快速和更低成本的发现软件故障,简化开发流程的复杂性。很多情况下,MTE 可以允许利用同一套二进制代码进行不同方式的内存安全测试。MTE产生的故障报告将和 ASAN 和 HWASAN 一样,非常详细而且有可操作性。
- 可以利用MTE在量产产品上进行复杂软件场景的测试。软件开发者和原始设备制造商可以针对某些软件协议栈模块,有选择的激活 MTE。而终端用户可以关闭 MTE, 或者在其同意的情况下激活 MTE 并且把相应的故障报告发回给软件开发者进行有效分析。
- MTE 可以强有力的缓解 Android 系统和应用程序中的大量内存安全故障。对于大多数此类故障,MTE 能够有 90% 以上的概率发现并缓解该故障被恶意利用的可能性。通过实现一系列安全保护措施,攻击者将不能针对安全敏感模块,反复发起攻击。