目录
概述
原理
使用
验证开启
对比asan
参考链接
概述
hwasan是Hardware Address Sanitizer的简称,它是clang llvm提供的一套内存错误检测系统,可以用来检测C/C++代码常见的内存错误
-
Stack and heap buffer overflow/underflow
-
Global buffer overflow/underflow
-
Heap use after free
-
Stack use outside scope
-
Double free/wild free
-
Initialization order bugs
相比与之前的asan(Address Sanitizer)它在性能、内存占用上都有不小的提升,但是由于它使用了依赖AArch64的Address tagging特性,所以只能在64位程序开启,目前只有Android 10.0及以上版本的AArch64默认支持了hwasan。
Address tagging特性允许应用程序自定义数据存储到虚拟地址的最高8位,当CPU在操作这个虚拟地址的时候会自动忽略它,称为Top byte ignore。
原理
-
将整个虚拟内存区间按照16:1的比例划分为user memory和shadow memory,无论是堆上、栈上还是全局对象他们的内存起始地址都按照16字节对齐,保证每16字节的user memory都能映射到1字节的shadow memory。
-
分配对象的时候,随机分配一个8位的随机tag标记到该对象的虚拟地址最高8位,同时将该tag也会保存到其映射的shadow memory中。
-
编译器在每个内存地址的load/store之前都会插入检查指令,用于确认操作的地址最高8位保存的tag与其映射的shadow memory中的tag值一致。
-
对象回收后也会重新分配一个随机值,保存到其映射的shadow memory中,一旦后面出现use after free就会检测到tag值不一致异常。
-
当分配的对象小于16字节时,多余的内存不会再分配给其它对象,此时shadow memory中保存的是对象所占内存的实际字节数,而tag值则保存在16字节的最后一个字节里面。
需要注意的是,HWASAN中normal memory和shadow memory的映射关系是16➡1,而ASAN中二者的映射关系是8➡1。
-
Use-After-Free
当一个堆内存被分配出来时,返回给用户空间的地址便已经带上了标签(存储于地址的高8位)。之后通过该地址进行内存访问,将先检测地址中的标签值和访问地址对应的shadow memory的值是否相等。如果相等则验证通过,可以进行正常的内存访问。 当该内存被free时,HWASAN会为该块区域分配一个新的随机值,存储于其对应的shadow memory中。如果此后再有新的访问,则地址中的标签值必然不等于shadow memory中存储的新的随机值,因此会有错误产生。
-
Heap-Over-Flow
想要检测HeapOverFlow,有一个前提需要满足:相邻的memory区域需要有不同的shadow memory值,否则将无法分辨两个不同的memory区域。为每个memory区域随机分配将有概率让两个相邻区域具有同样的shadow memory值,虽然概率比较小(1/256),但总归是个缺陷。
使用
单个程序:-fsanitize=hwaddress
整个rom:添加环境变量SANITIZE_TARGET=hwaddress ;ENABLE_SYSTEM_MTBF=true
验证开启
adb shell getprop | grep "hwasan"
对比asan
tag由单字节表示,可以反映8个真实内存字节的状态。生成时根据该块内存的实际状态选取tag值,因此tag值具有事先规定的含义。0x00表示8个字节均可访问,0x01表示8个字节中只有第一个字节可以访问,0xFD表示这块内存已经被释放。
参考链接
官方介绍:https://source.android.google.cn/docs/security/test/hwasan?hl=zh-cn
asan与hwasan对比:https://cloud.tencent.com/developer/article/1657154
MTE技术:https://juejin.cn/post/7013595058125406238
关于hwasan的详细介绍可以参考:
https://arxiv.org/pdf/1802.09517.pdf
Hardware-assisted AddressSanitizer Design Documentation — Clang 18.0.0git documentation