实际上,一个byte可以编码的状态总共有256(2^8)种,因此用在这里绰绰有余。

和ASAN相比,HWASAN具有哪些缺点?

Shadow memory和normal memory的映射关系如上图所示。一个byte的shadow memory反映8个byte normal memory的状态。那如何根据normal memory的地址找到它对应的shadow memory呢?

对于64位机器上的Android而言,二者的转换公式如下:

Shadow memory address = (Normal memory address 》》 3) + 0x100000000

右移三位的目的是为了完成 81的映射,而加一个offset是为了和Normal memory区分开来。最终内存空间种会存在如下的映射关系:

和ASAN相比,HWASAN具有哪些缺点?

Bad代表的是shadow memory的shadow memory,因此其中数据没有意义,该内存区域不可使用。

上文中提到,8字节组成的memory region共有9中状态:

1~7个字节可寻址(共七种),shadow memory的值为1~7。

8个字节都可寻址,shadow memory的值为0。

0个字节可寻址,shadow memory的值为负数。

为什么0个字节可寻址的情况shadow memory不为0,而是负数呢?是因为0个字节可寻址其实可以继续分为多种情况,譬如:

这块区域是heap redzones

这块区域是stack redzones

这块区域是global redzones

这块区域是freed memory

对所有0个字节可寻址的normal memory region的访问都是非法的,ASAN将会报错。而根据其shadow memory的值便可以具体判断是哪一种错。

Shadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa (实际上Heap right redzone也是fa) Freed Heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb Shadow gap: cc

1.2 检测算法

ShadowAddr = (Addr 》》 3) + Offset;k = *ShadowAddr;if (k != 0 && ((Addr & 7) + AccessSize 》 k)) ReportAndCrash(Addr);

在每次内存访问时,都会执行如上的伪代码,以判断此次内存访问是否合规。

首先根据normal memory的地址找到对应shadow memory的地址,然后取出其中存取的byte值:k。

k!=0,说明Normal memory region中的8个字节并不是都可以被寻址的。