Google 致力于为黑人社区推动种族平等。查看具体举措

HWAddressSanitizer

硬件辅助的 AddressSanitizer (HWASan) 是一款类似于 AddressSanitizer 的内存错误检测工具。与 ASan 相比,HWASan 使用的内存少得多,因而更适合用于对整个系统执行排错。HWASan 仅适用于 Android 10 及更高版本,且只能用于 AArch64 硬件。您可以通过 ci.android.com,将预构建的 HWASan 映像刷写到支持的 Pixel 设备上(详细设置说明)。

与传统的 ASan 相比,HWASan 具有如下特征:

  • 类似的 CPU 开销(约为 2 倍)
  • 类似的代码大小开销 (40 - 50%)
  • 更小的 RAM 开销 (10% - 35%)

HWASan 能检测到 ASan 所能检测到的同一系列错误:

  • 堆栈和堆缓冲区上溢/下溢
  • 释放之后的堆使用情况
  • 超出范围的堆栈使用情况
  • 重复释放/错误释放

此外,HWASan 还可以检测返回之后的堆栈使用情况。

实现详情和限制

HWASan 基于内存标记方法,在这种方法中,小的随机标记值同时与指针和内存地址范围相关联。为使内存访问有效,指针和内存标记必须匹配。HWASan 依赖于 ARMv8 功能 Top-Byte-Ignore(TBI,也称为虚拟地址标记)将指针标记存储在地址的最高位。

如需详细了解 HWASan 的设计,请前往 Clang 文档所在的网站。

从设计上讲,ASan 对检测上溢规定了有限大小的红色区域,并对检测释放后使用情况规定了有限容量隔离区,而 HWASan 则没有这些规定。因此,无论上溢有多大或内存在多久之前解除分配,HWASan 都可以检测到错误。这赋予 HWASan 比 ASan 大得多的优势。

不过,HWASan 具有有限数量的可能标记值(256 个),这意味着在一次程序执行期间忽略任何错误的概率为 0.4%。

要求

HWASan 要求 Linux 内核接受系统调用参数中被标记的指针。在以下上游补丁程序集中实现了对此项要求的支持:

android-4.14 及更高分支中的通用 Android 内核以向后移植的形式提供这些补丁程序,但 Android 10 专属分支(例如 android-4.14-q)未以向后移植的形式提供这些补丁程序。

Android 11 开始提供对 HWASan 的用户空间支持。

如果您要使用自定义工具链进行构建,请确保它包含直到 LLVM 提交 c336557f 的所有内容。

使用 HWASan

如需使用 HWASan 构建整个平台,请使用以下命令:

lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j

为方便起见,您可以向产品定义中添加 SANITIZE_TARGET 设置,与 aosp_coral_hwasan 类似。

与 ASan 不同,使用 HWASan 时无需构建两次,只需增量构建,没有特殊的刷写指令,不需要擦除,支持静态可执行文件,并且可以跳过对除 libc 之外的任何库的排错。此外,也不要求在对库进行排错后必须同时对链接到该库的任何可执行文件进行排错。

如需跳过对某个模块的排错,请使用 LOCAL_NOSANITIZE := hwaddresssanitize: { hwaddress: false }

单个模块可使用 HWASan 进行排错,前提是 libc 也要使用 HWASan 进行排错。为此,可将 sanitize: { hwaddress: true } 添加到相应的 Android.bp 模块定义。如果使用的是以 _hwasan 为后缀的 build(包括 libc),则表示整个 Android 平台都是使用 HWASan 构建的,因此对于 HWASan build,您无需手动对 libc 进行排错。

更出色的堆栈轨迹

HWASan 使用基于帧指针的快速展开程序 (unwinder),根据程序中的每个内存分配和取消分配事件来记录堆栈跟踪信息。默认情况下,Android 在 AArch64 代码中启用帧指针,因此这在实际操作中非常有用。如果您需要通过托管代码展开,请在进程环境中设置 HWASAN_OPTIONS=fast_unwind_on_malloc=0。请注意,错误的内存访问堆栈跟踪会默认使用“慢速”展开程序;此设置仅影响分配和取消分配跟踪。此选项可能对 CPU 要求极高,具体取决于负载。

符号化

请参阅 ASan 文档中的符号化

在应用中使用 HWASan

与 AddressSanitizer 类似,HWASan 无法检查 Java 代码,但可以检测 JNI 库中的错误。而与 ASan 不同的是,支持在非 HWASan 设备上运行 HWASan 应用。

在 HWASan 设备上,可以使用 HWASan 检查应用,方法是使用 Make 中的 SANITIZE_TARGET:=hwaddress 或编译器标记中的 -fsanitize=hwaddress 来构建代码。 如需了解详情,请参阅应用开发者文档