HWAddress Sanitizer

The Android NDK supports HWAddress Sanitizer beginning with NDK r21 and Android 10 (API level 29).

HWASan is a memory error detection tool similar to ASan. 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 also detects:

  • Stack use after return

Setup

HWASan applications need a HWASan build of Android to run. You can flash prebuilt HWASan images to supported Pixel devices. The builds are available on ci.android.com, where you can click on the exact build (square) you want to get a Flash Build link. This requires that you know the codename for your phone.

Flash a device build

It may be easier to instead go straight to flash.android.com because there the flow starts with detecting your device and only shows you builds you can use. The following images illustrate the setup flow in this tool.

Enable developer mode on your device and connect it to your computer using a USB cable. Click Add new device, select your device from the dialog, and click Connect.

Detect a device to flash Select the device to connect to

Once your device is connected, you will need to click it to configure the build. In the Select a build ID box, select the aosp-master-with-phones-throttled branch to automatically choose the correct image for the device you have connected.

Select the device to flash Confirm flash options and flash the device

Click Install to flash your device.

There's more detail about the necessary set up in the Android Flash Tool documentation. Alternatively, you can check the AOSP documentation for instructions for building a HWASan image from source.

Build

To build your app's native (JNI) code with HWAddress Sanitizer, do the following:

ndk-build

In your Application.mk file:

APP_STL := c++_shared # Or system, or none, but not c++_static.
APP_CFLAGS := -fsanitize=hwaddress -fno-omit-frame-pointer
APP_LDFLAGS := -fsanitize=hwaddress

CMake

In your module's build.gradle file:

android {
    defaultConfig {
        externalNativeBuild {
            cmake {
                # Can also use system or none as ANDROID_STL, but not c++_static.
                arguments "-DANDROID_STL=c++_shared"
            }
        }
    }
}

For each target in your CMakeLists.txt:

target_compile_options(${TARGET} PUBLIC -fsanitize=hwaddress -fno-omit-frame-pointer)
set_target_properties(${TARGET} PROPERTIES LINK_FLAGS -fsanitize=hwaddress)

Run

Run the app as usual on a HWASan-built Android image. When a memory error is detected, an app will crash with SIGABRT and print a detailed message to logcat. A copy of the message can be found in a file under /data/tombstones and will look like this:

ERROR: HWAddressSanitizer: tag-mismatch on address 0x0042a0826510 at pc 0x007b24d90a0c
WRITE of size 1 at 0x0042a0826510 tags: 32/3d (ptr/mem) in thread T0
    #0 0x7b24d90a08  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x2a08)
    #1 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)
    #2 0x7b8f1db364  (/apex/com.android.art/lib64/libart.so+0x18f364)
    #3 0x7b8f2ad8d4  (/apex/com.android.art/lib64/libart.so+0x2618d4)

0x0042a0826510 is located 0 bytes to the right of 16-byte region [0x0042a0826500,0x0042a0826510)
allocated here:
    #0 0x7b92a322bc  (/apex/com.android.runtime/lib64/bionic/libclang_rt.hwasan-aarch64-android.so+0x212bc)
    #1 0x7b24d909e0  (/data/app/com.example.hellohwasan-eRpO2UhYylZaW0P_E0z7vA==/lib/arm64/libnative-lib.so+0x29e0)
    #2 0x7b8f1e4ccc  (/apex/com.android.art/lib64/libart.so+0x198ccc)

The message may be followed by additional debugging infomation, such as the list of live threads in the application, tags of nearby memory allocations, CPU register values and so on.