Informationen zum Lesen von HWASan-Abstürzen finden Sie unter HWASan-Berichte verstehen.
Hardware-assisted AddressSanitizer (HWASan) ist ein Tool zur Erkennung von Arbeitsspeicherfehlern, das AddressSanitizer ähnelt. HWASan verwendet viel weniger RAM als ASan und eignet sich daher für die Bereinigung des gesamten Systems. HWASan ist nur unter Android 10 und höher und nur auf AArch64-Hardware verfügbar.
HWASan ist zwar in erster Linie für C/C++-Code nützlich, kann aber auch beim Debuggen von Java-Code helfen, der Abstürze in C/C++ verursacht, das zur Implementierung von Java-Schnittstellen verwendet wird. Das ist hilfreich, weil es Speicherfehler erkennt, wenn sie auftreten, und Sie direkt auf den verantwortlichen Code hinweist.
Im Vergleich zu klassischem ASan bietet HWASan folgende Vorteile:
- Ähnlicher CPU-Overhead (~2-fach)
- Ähnlicher Code-Overhead (40–50%)
- Viel geringerer RAM-Overhead (10 – 35 %)
HWASan erkennt dieselben Fehler wie ASan:
- Stack- und Heap-Pufferüberlauf/-unterlauf
- Heap-Nutzung nach dem Freigeben
- Stack-Nutzung außerhalb des Anwendungsbereichs
- Double Free/Wild Free
Außerdem erkennt HWASan die Verwendung des Stacks nach der Rückgabe.
HWASan (wie ASan) ist mit UBSan kompatibel. Beide können gleichzeitig auf einem Ziel aktiviert werden.
Details zur Implementierung und Einschränkungen
HWASan basiert auf dem Ansatz Memory Tagging, bei dem sowohl Zeigern als auch Speicheradressbereichen ein kleiner zufälliger Tag-Wert zugewiesen wird. Damit ein Speicherzugriff gültig ist, müssen die Zeiger- und Speichertags übereinstimmen. HWASan nutzt die ARMv8-Funktion „Top Byte Ignore“ (TBI), auch Virtual Address Tagging genannt, um das Pointer-Tag in den höchsten Bits der Adresse zu speichern.
Weitere Informationen zum Design von HWASan finden Sie in der Clang-Dokumentation.
HWASan hat von Natur aus nicht die Redzones mit begrenzter Größe von ASan zum Erkennen von Überläufen oder die Quarantäne mit begrenzter Kapazität von ASan zum Erkennen von „Use-After-Free“-Fehlern. Aus diesem Grund kann HWASan einen Fehler erkennen, unabhängig davon, wie groß der Überlauf ist oder wie lange es her ist, dass der Speicher freigegeben wurde. Das ist ein großer Vorteil von HWASan gegenüber ASan.
HWASan hat jedoch eine begrenzte Anzahl möglicher Tag-Werte (256). Das bedeutet, dass bei einer Ausführung des Programms eine Wahrscheinlichkeit von 0,4% besteht, dass ein Fehler nicht erkannt wird.
Voraussetzungen
Aktuelle Versionen (4.14+) des gemeinsamen Android-Kernels unterstützen HWASan sofort. Die Android 10-spezifischen Branches unterstützen HWASan nicht.
Die Unterstützung von HWASan im Userspace ist ab Android 11 verfügbar.
Wenn Sie mit einem anderen Kernel arbeiten, muss der Linux-Kernel getaggte Zeiger in Systemaufrufargumenten akzeptieren, damit HWASan funktioniert. Die Unterstützung dafür wurde in den folgenden Upstream-Patchsets implementiert:
- ABI für arm64-Adressen mit Tag
- arm64: Nutzerzeiger, die an den Kernel übergeben werden, nicht taggen
- mm: Avoid creating virtual address aliases in brk()/mmap()/mremap()
- arm64: Validate tagged addresses in access_ok() called from kernel threads
Wenn Sie eine benutzerdefinierte Toolchain verwenden, muss diese alles bis zum LLVM-Commit c336557f enthalten.
HWASan verwenden
Verwenden Sie die folgenden Befehle, um die gesamte Plattform mit HWASan zu erstellen:
lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j
Sie können die Einstellung SANITIZE_TARGET einer Produktdefinition hinzufügen, ähnlich wie bei aosp_coral_hwasan.
Für Nutzer, die mit AddressSanitizer vertraut sind, ist die Komplexität des Builds deutlich geringer:
- Sie müssen „make“ nicht zweimal ausführen.
- Inkrementelle Builds funktionieren sofort.
- Es ist nicht erforderlich, Nutzerdaten zu flashen.
Einige AddressSanitizer-Einschränkungen sind ebenfalls aufgehoben:
- Statische ausführbare Dateien werden unterstützt.
- Es ist in Ordnung, die Bereinigung für alle Ziele außer „libc“ zu überspringen. Im Gegensatz zu ASan gibt es keine Anforderung, dass jede ausführbare Datei, die eine bereinigte Bibliothek verknüpft, ebenfalls bereinigt werden muss.
Der Wechsel zwischen HWASan und regulären Images mit derselben (oder einer höheren) Build-Nummer ist jederzeit möglich. Das Gerät muss nicht auf die Werkseinstellungen zurückgesetzt werden.
Wenn Sie die Bereinigung eines Moduls überspringen möchten, verwenden Sie LOCAL_NOSANITIZE := hwaddress
(Android.mk) oder sanitize: { hwaddress: false }
(Android.bp).
Einzelne Ziele bereinigen
HWASan kann in einem regulären (nicht bereinigten) Build pro Ziel aktiviert werden, sofern libc.so
ebenfalls bereinigt wird. Fügen Sie hwaddress: true
dem Bereinigungsblock in "libc_defaults"
in bionic/libc/Android.bp hinzu. Wiederholen Sie den Vorgang dann für das Ziel, an dem Sie gerade arbeiten.
Durch die Bereinigung von libc können Heap-Speicherzuweisungen systemweit getaggt und die Tags für Speichervorgänge in libc.so
geprüft werden. So können Fehler auch in Binärdateien erkannt werden, für die HWASan nicht aktiviert wurde, wenn der fehlerhafte Speicherzugriff in libc.so
erfolgt (z. B. pthread_mutex_unlock()
für einen delete()
ed-Mutex.
Wenn die gesamte Plattform mit HWASan erstellt wird, müssen keine Build-Dateien geändert werden.
Bessere Stacktraces
HWASan verwendet einen schnellen, Frame-Pointer-basierten Unwinder, um für jedes Speicherzuweisungs- und ‑freigabeereignis im Programm einen Stack-Trace aufzuzeichnen. In Android sind Frame-Pointer im AArch64-Code standardmäßig aktiviert. Das funktioniert in der Praxis also sehr gut. Wenn Sie durch verwalteten Code zurückgehen müssen, legen Sie HWASAN_OPTIONS=fast_unwind_on_malloc=0
in der Prozessumgebung fest. Hinweis: Für Stack-Traces mit schlechtem Speicherzugriff wird standardmäßig der „langsame“ Unwinder verwendet. Diese Einstellung wirkt sich nur auf Zuweisungs- und Freigabe-Traces aus. Diese Option kann je nach Last sehr CPU-intensiv sein.
Symbolisierung
Weitere Informationen finden Sie unter Symbolisierung im Abschnitt „HWASan-Berichte verstehen“.
HWASan in Apps
Ähnlich wie AddressSanitizer kann HWASan nicht in Java-Code sehen, aber Fehler in den JNI-Bibliotheken erkennen. Bis Android 14 wurde die Ausführung von HWASan-Apps auf einem Nicht-HWASan-Gerät nicht unterstützt.
Auf einem HWASan-Gerät können Apps mit HWASan geprüft werden, indem ihr Code mit SANITIZE_TARGET:=hwaddress
in Make oder -fsanitize=hwaddress
in Compiler-Flags erstellt wird.
Auf einem Gerät, das nicht HWASan unterstützt (mit Android 14 oder höher), muss eine wrap.sh-Datei mit der Einstellung LD_HWASAN=1
hinzugefügt werden.
Weitere Informationen finden Sie in der Dokumentation für App-Entwickler.