HWAddressSanitizer

Hardware-assisted AddressSanitizer (HWASan) is a memory error detection tool similar to AddressSanitizer. HWASan uses a lot less RAM compared to ASan, which makes it suitable for whole system sanitization. HWASan is only available on Android Q and higher, and on AArch64 hardware.

Compared to classic ASan, HWASan has:

  • Similar CPU overhead (~2x)
  • Similar code size overhead (40 – 50%)
  • Much smaller RAM overhead (10% – 35%)

HWASan detects the same set of bugs as ASan:

  • Stack and heap buffer overflow/underflow
  • Heap use after free
  • Stack use outside scope
  • Double free/wild free

Additionally, HWASan detects stack use after return.

Implementation details and limitations

HWASan is based on the memory tagging approach, where a small random tag value is associated both with pointers and with ranges of memory addresses. For a memory access to be valid, the pointer and memory tags have to match. HWASan relies on ARMv8 feature top byte ignore (TBI), also called virtual address tagging, to store the pointer tag in the highest bits of the address.

You can read more about the design of HWASan on the Clang documentation site.

By design, HWASan doesn't have ASan's limited-size redzones for detecting overflows or ASan's limited-capacity quarantine for detecting use after free. For this reason, HWASan can detect a bug no matter how large the overflow is or how long ago the memory was deallocated. This gives HWASan a big advantage over ASan.

However, HWASan has a limited number of possible tag values (256), which means that there is a 0.4% probability of missing any bug during one execution of the program.

HWASan requires the Linux kernel to accept tagged pointers in system call arguments. This isn't supported in the common kernel currently, so supporting a device requires backporting the arm64: untag user pointers passed to the kernel patch series.

Several branches of the AOSP kernel source repository contain the necessary backports, but none of the prebuilt kernels do. Until the binary kernel repositories are updated, using HWASan in AOSP requires building the kernel from source.

Userspace support for HWASan in Android requires changes from January 2019, which are only available in the master branch of AOSP. Pixel 2, 3, and 3a are known to work with an entire system built with HWASan.

Using HWASan

Use the following commands to build the entire platform using HWASan:

lunch aosp_walleye-userdebug # (or any other product)
make SANITIZE_TARGET=hwaddress

Unlike ASan, with HWASan there's no need to build twice. Incremental builds just work, there are no special flashing instructions or wiping requirement, static executables are supported, and it's okay to skip sanitization of any library other than libc. There's also no requirement that if a library is sanitized, any executable that links to it must also be sanitized.

To skip sanitization of a module, use LOCAL_NOSANITIZE := hwaddress or sanitize: { hwaddress: false }.

Better stack traces

HWASan uses a fast, frame-pointer-based unwinder to record a stack trace for every memory allocation and deallocation event in the program. Android enables frame pointers in AArch64 code by default, so this works great in practice. If you need to unwind through managed code, set HWASAN_OPTIONS=fast_unwind_on_malloc=0 in the process environment. Note that bad memory access stack traces use the "slow" unwinder by default; this setting only affects allocation and deallocation traces. This option can be very CPU-intensive, depending on the load.

Symbolization

See Symbolization in ASan documentation.

HWASan in apps

Similar to AddressSanitizer, HWASan can't see into Java code, but it can detect bugs in the JNI libraries. Unlike ASan, running HWASan apps on a non-HWASan device is not supported.

On a HWASan device, apps can be checked with HWASan by building their code with SANITIZE_TARGET:=hwaddress in Make, or -fsanitize=hwaddress in compiler flags.