Hardware-unterstützte AddressSanitizer

Informationen zum Lesen von HWASan-Abstürzen findest du unter Informationen zu HWASan-Berichten.

Hardware-assisted AddressSanitizer (HWASan) ist ein Tool zur Erkennung von Arbeitsspeicherfehlern, das AddressSanitizer ähnelt. HWASan benötigt im Vergleich zu ASan viel weniger RAM, was es für die Bereinigung des gesamten Systems geeignet macht. HWASan ist nur mit 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 zum Debuggen von Java-Code beitragen, der Abstürze in C/C++ verursacht, der zur Implementierung von Java-Schnittstellen verwendet wird. Es ist hilfreich, weil es Speicherfehler erkennt, sobald sie auftreten, und Sie direkt auf den Code verweist, der dafür verantwortlich ist.

Sie können vorkonfigurierte HWASan-Images von ci.android.com auf unterstützte Pixel-Geräte flashen (detaillierte Einrichtungsanleitung).

Im Vergleich zur klassischen ASan bietet HWASan:

  • Ähnlicher CPU-Overhead (~2x)
  • Aufwand mit ähnlicher Codegröße (40–50%)
  • Viel geringerer RAM-Overhead (10 % bis 35%)

HWASan erkennt dieselben Fehler wie ASan:

  • Stack- und Heap-Pufferüberlauf/-unterlauf
  • Heap-Nutzung nach kostenloser Nutzung
  • Stack außerhalb des Gültigkeitsbereichs verwendet
  • Double Free/Wild Free

Darüber hinaus erkennt HWASan die Stacknutzung nach der Rückkehr.

HWASan (wie ASan) ist mit UBSan kompatibel und beide können gleichzeitig auf einem Ziel aktiviert werden.

Implementierungsdetails und Einschränkungen

HWASan basiert auf dem Ansatz des Speicher-Taggings, bei dem ein kleiner zufälliger Tagwert sowohl mit Pointern als auch mit Speicheradressenbereichen verknüpft wird. Damit ein Speicherzugriff gültig ist, müssen die Zeiger- und Speicher-Tags übereinstimmen. HWASan nutzt die ARMv8-Funktion „Top Byte Ignore“ (TBI), auch virtuelles Adress-Tagging genannt, um das Zeiger-Tag in den höchsten Bits der Adresse zu speichern.

Weitere Informationen zum Design von HWASan finden Sie auf der Clang-Dokumentationswebsite.

HWASan verfügt nicht über die von ASan begrenzten roten Zonen zum Erkennen von Überläufen oder die Quarantäne von ASan mit begrenzter Kapazität, um die Nutzung nach der Freischaltung zu erkennen. Aus diesem Grund kann HWASan einen Fehler erkennen, unabhängig davon, wie groß der Überlauf ist oder wie lange der Speicher zuvor deallociert wurde. Das bietet HWASan einen großen Vorteil gegenüber ASan.

HWASan hat jedoch eine begrenzte Anzahl möglicher Tag-Werte (256), was bedeutet, dass bei einer Ausführung des Programms mit einer Wahrscheinlichkeit von 0,4% ein Fehler übersehen wird.

Voraussetzungen

Neuere Versionen (ab 4.14) des allgemeinen Android-Kernels unterstützen HWASan standardmäßig. Die Android 10-spezifischen Branches unterstützen HWASan nicht.

Der Userspace-Support für HWASan ist ab Android 11 verfügbar.

Wenn Sie mit einem anderen Kernel arbeiten, muss der Linux-Kernel für HWASan getaggte Zeiger in Systemaufrufargumenten akzeptieren. Die Unterstützung dafür wurde in den folgenden Upstream-Patch-Sets implementiert:

Wenn Sie mit einer benutzerdefinierten Toolchain erstellen, muss diese alles bis zum LLVM-Commit c336557f enthalten.

HWASan verwenden

Mit den folgenden Befehlen können Sie die gesamte Plattform mit HWASan 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 Build-Komplexität deutlich geringer:

  • Du musst die Aktion nicht zweimal ausführen.
  • Inkrementelle Builds sind sofort einsatzbereit.
  • Es ist nicht erforderlich, Nutzerdaten zu flashen.

Auch einige Einschränkungen von AddressSanitizer wurden aufgehoben:

  • Statische ausführbare Dateien werden unterstützt.
  • Sie können die Bereinigung aller Ziele außer libc überspringen. Im Gegensatz zu ASan ist es nicht erforderlich, dass eine ausführbare Datei, die mit einer Bibliothek verknüpft ist, ebenfalls bereinigt wird, wenn die Bibliothek bereinigt wird.

Der Wechsel zwischen HWASan- und regulären Images mit derselben (oder höheren) Build-Nummer ist jederzeit möglich. Das Gerät muss nicht gelöscht 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, solange auch libc.so bereinigt wird. Fügen Sie hwaddress: true dem Sanitizer-Block in "libc_defaults" in bionic/libc/Android.bp hinzu. Wiederholen Sie diesen Vorgang für das Ziel, an dem Sie gerade arbeiten.

Durch das Bereinigen von libc können die Heap-Speicherzuweisungen systemweit getaggt und die Tags auf Arbeitsspeichervorgänge in libc.so geprüft werden. Dadurch können Fehler auch in Binärdateien erkannt werden, in denen HWASan nicht aktiviert war, wenn sich der fehlerhafte Arbeitsspeicherzugriff in libc.so befindet (z. B. pthread_mutex_unlock() auf einem delete()ed Mutex).

Wenn die gesamte Plattform mit HWASan erstellt wird, müssen keine Build-Dateien geändert werden.

Flashstation

Für Entwicklungszwecke können Sie mit Flashstation ein HWASan-kompatibles AOSP-Build auf ein Pixel mit entsperrtem Bootloader flashen. Wählen Sie das Ziel „_hwasan“ aus, z.B. „aosp_flame_hwasan-userdebug“. Weitere Informationen finden Sie in der NDK-Dokumentation für HWASan für App-Entwickler.

Bessere Stacktraces

HWASan verwendet einen schnellen, Framepointer-basierten Abwickler, um für jede Arbeitsspeicherzuweisung und jedes Deallocation-Ereignis im Programm einen Stacktrace aufzuzeichnen. Android aktiviert standardmäßig Frame-Pointer im AArch64-Code, was in der Praxis sehr gut funktioniert. Wenn Sie verwalteten Code zurückspulen müssen, legen Sie HWASAN_OPTIONS=fast_unwind_on_malloc=0 in der Prozessumgebung fest. Hinweis: Für Stack-Traces mit fehlerhaftem Speicherzugriff wird standardmäßig der „langsame“ Unwinder verwendet. Diese Einstellung wirkt sich nur auf die Zuweisungs- und Deaktivierungs-Traces aus. Diese Option kann je nach Auslastung sehr CPU-intensiv sein.

Symbolisierung

Weitere Informationen finden Sie unter Symbolisierung in „Informationen zu HWASan-Berichten“.

HWASan in Apps

Ähnlich wie AddressSanitizer kann HWASan nicht in Java-Code eindringen, aber Fehler in den JNI-Bibliotheken erkennen. Bis Android 14 wurde das Ausführen von HWASan-Apps auf einem Gerät ohne HWASan nicht unterstützt.

Auf einem HWASan-Gerät können Apps mit HWASan geprüft werden, indem der Code mit SANITIZE_TARGET:=hwaddress in Make oder -fsanitize=hwaddress in Compiler-Flags erstellt wird. Auf Geräten ohne HWASan mit Android 14 oder höher muss die Dateieinstellung „wrap.sh“ LD_HWASAN=1 hinzugefügt werden. Weitere Informationen finden Sie in der Dokumentation für App-Entwickler.