AddressSanitizer

AddressSanitizer (ASan) ist ein schnelles compilerbasiertes Tool zum Erkennen von Speicherfehlern in nativem Code.

ASan erkennt:

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

ASan wird sowohl auf 32-Bit- als auch auf 64-Bit-ARM sowie x86 und x86-64 ausgeführt. Der CPU-Overhead von ASan ist etwa doppelt so hoch, der Codegrößen-Overhead liegt zwischen 50 % und dem Doppelten und es gibt einen großen Arbeitsspeicher-Overhead (je nach Allokationsmuster, aber in der Größenordnung von 2 x).

Android 10 und der AOSP-Hauptzweig auf AArch64 unterstützen Hardware-assisted AddressSanitizer (HWASan), ein ähnliches Tool mit geringerem RAM-Overhead und einer größeren Bandbreite an erkannten Fehlern. HWASan erkennt zusätzlich zu den von ASan erkannten Fehlern die Verwendung des Stacks nach der Rückkehr.

HWASan hat einen ähnlichen CPU- und Codegröße-Overhead, aber einen viel geringeren RAM-Overhead (15%). HWASan ist nicht deterministisch. Es gibt nur 256 mögliche Tag-Werte, sodass es einen festen Wert von 0,4 % gibt, Wahrscheinlichkeit, dass Sie einen Fehler übersehen. HWASan hat nicht die begrenzten roten Zonen von ASan zur Erkennung von Überläufen und begrenzter Kapazität zur Erkennung von Use-After-Free-Angriffen, HWASan spielt also keine Rolle, wie groß der Überlauf ist oder wie lange wurde freigegeben. Dadurch ist HWASan besser als ASan. Weitere Informationen zum Design von HWASan oder zur Verwendung von HWASan auf Android-Geräten

ASan erkennt neben Heap-Overflows auch Stack-/globale Overflows und ist schnell mit minimalem Arbeitsspeicheraufwand.

In diesem Dokument wird beschrieben, wie Sie Teile oder das gesamte Android-System mit ASan erstellen und ausführen. Wenn Sie eine SDK/NDK-App mit ASan erstellen, lesen Sie Adressbereinigung .

Einzelne ausführbare Dateien mit ASan bereinigen

Fügen Sie der Build-Regel für die ausführbare Datei LOCAL_SANITIZE:=address oder sanitize: { address: true } hinzu. Sie können im Code nach vorhandenen Beispielen oder nach den anderen verfügbaren Sanitizern suchen.

Wenn ein Fehler erkannt wird, druckt ASan einen ausführlichen Bericht sowohl an die Standard- in logcat und stürzt dann den Prozess ab.

Gemeinsam genutzte Bibliotheken mit ASan bereinigen

Aufgrund der Funktionsweise von ASan kann eine mit ASan erstellte Bibliothek nur von einer mit ASan erstellten ausführbaren Datei verwendet werden.

Wenn Sie eine freigegebene Bibliothek, die in mehreren ausführbaren Dateien verwendet wird, die nicht alle mit ASan erstellt wurden, bereinigen möchten, benötigen Sie zwei Kopien der Bibliothek. Wir empfehlen, Folgendes zu Android.mk für das betreffende Modul hinzuzufügen:

LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

Dadurch wird die Bibliothek in /system/lib/asan statt in /system/lib platziert. Führen Sie dann die ausführbare Datei mit folgendem Befehl aus:

LD_LIBRARY_PATH=/system/lib/asan

Fügen Sie für Systemdaemons Folgendes in den entsprechenden Abschnitt von /init.rc oder /init.$device$.rc ein.

setenv LD_LIBRARY_PATH /system/lib/asan

Prüfen Sie, ob der Prozess Bibliotheken von /system/lib/asan verwendet, falls vorhanden. Lesen Sie dazu /proc/$PID/maps. Ist dies nicht der Fall, müssen Sie , um SELinux zu deaktivieren:

adb root
adb shell setenforce 0
# restart the process with adb shell kill $PID
# if it is a system service, or may be adb shell stop; adb shell start.

Bessere Stacktraces

ASan verwendet eine schnelle, auf Framepointer basierende Abwicklung, um einen Stack aufzuzeichnen. für jedes Arbeitsspeicherzuweisungs- und Deallocation-Ereignis im Programm. Meiste von Android ohne Frame-Pointer. Daher erhalten Sie oft nur ein oder zwei aussagekräftige Frames. Um dieses Problem zu beheben, erstellen Sie die Bibliothek neu mit ASan (empfohlen!) oder mit:

LOCAL_CFLAGS:=-fno-omit-frame-pointer
LOCAL_ARM_MODE:=arm

Sie können auch ASAN_OPTIONS=fast_unwind_on_malloc=0 in der Prozessumgebung festlegen. Letztere kann sehr CPU-intensiv sein, je nachdem, die Last.

Symbolisierung

Ursprünglich enthalten ASan-Berichte Verweise auf Abweichungen in Binärdateien und freigegebenen Bibliotheken. Es gibt zwei Möglichkeiten, Informationen zu Quelldatei und -zeile abzurufen:

  • Prüfen Sie, ob die llvm-symbolizer-Binärdatei in /system/bin vorhanden ist. llvm-symbolizer basiert auf Quellen in third_party/llvm/tools/llvm-symbolizer.
  • Filtern Sie den Bericht mit dem external/compiler-rt/lib/asan/scripts/symbolize.py-Script.

Bei der zweiten Methode können mehr Daten bereitgestellt werden (d. h. file:line Standorte), weil Verfügbarkeit von symbolisierten Bibliotheken auf dem Host

ASan in Apps

ASan kann keinen Java-Code sehen, aber Fehler in der JNI erkennen. Bibliotheken. Dazu müssen Sie die ausführbare Datei mit ASan erstellen, in diesem Fall /system/bin/app_process(32|64). Dieses aktiviert ASan in allen Apps auf dem Gerät gleichzeitig, was eine aber ein Gerät mit 2 GB RAM sollte damit umgehen können.

Fügen Sie LOCAL_SANITIZE:=address zur app_process-Build-Regel in frameworks/base/cmds/app_process hinzu. Ignorieren das app_process__asan-Ziel vorerst in derselben Datei (falls es als Sie dies gelesen haben).

Bearbeiten Sie den Abschnitt service zygote der entsprechenden system/core/rootdir/init.zygote(32|64).rc-Datei, um dem Block mit den eingerückten Zeilen, die class main enthalten, die folgenden Zeilen hinzuzufügen, die ebenfalls um denselben Betrag eingerückt sind:

    setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib
    setenv ASAN_OPTIONS allow_user_segv_handler=true

Build, ADB-Synchronisierung, Fastboot Flash Boot und Neustart.

Attribut „wrap“ verwenden

Beim Ansatz im vorherigen Abschnitt wird ASan in jede in jeden Nachfolger der Zygote- Prozess). Es ist möglich, nur eine (oder mehrere) Apps mit ASan, und einen Teil des Arbeitsspeicher- aufwands gegen einen langsameren Start der App.

Sie können dazu die Property wrap. verwenden. Im folgenden Beispiel wird die Gmail App unter ASan ausgeführt:

adb root
adb shell setenforce 0  # disable SELinux
adb shell setprop wrap.com.google.android.gm "asanwrapper"

In diesem Zusammenhang schreibt asanwrapper /system/bin/app_process in /system/bin/asan/app_process um, das mit ASan erstellt wurde. Außerdem wird /system/lib/asan am Anfang von dynamischen Bibliothekssuchpfad hinzu. So werden ASan-instrumentierte Bibliotheken aus /system/lib/asan bei der Ausführung mit asanwrapper normalen Bibliotheken in /system/lib vorgezogen.

Wird ein Fehler gefunden, stürzt die App ab und der Bericht wird Protokoll.

SANITIZE_ZIEL

Android 7.0 und höher unterstützt die Entwicklung der gesamten Android-Plattform mit ASan auf einmal. (Wenn Sie eine höhere Version als Android 9 entwickeln, ist HWASan die bessere Wahl.)

Führen Sie die folgenden Befehle in derselben Build-Struktur aus.

make -j42
SANITIZE_TARGET=address make -j42

In diesem Modus enthält userdata.img zusätzliche Bibliotheken und muss ebenfalls auf das Gerät geflasht werden. Verwenden Sie die folgende Befehlszeile:

fastboot flash userdata && fastboot flashall

Dadurch werden zwei gemeinsam genutzte Bibliotheken erstellt: eine normale in /system/lib (die erste make-Aufruf) und eine mit ASan instrumentierte in /data/asan/lib (die zweite make-Aufruf). Ausführbare Dateien aus dem zweiten Build überschreiben die aus dem ersten Build. ASan-instrumentierte ausführbare Dateien erhalten einen anderen Bibliothekssuchpfad, der /data/asan/lib vor /system/lib enthält, da /system/bin/linker_asan in PT_INTERP verwendet wird.

Das Build-System überschreibt Zwischenobjektverzeichnisse, wenn sich der Wert von $SANITIZE_TARGET geändert hat. Dadurch wird ein Neuaufbau aller Ziele erzwungen, während die installierten Binärdateien unter /system/lib erhalten bleiben.

Einige Ziele können nicht mit ASan erstellt werden:

  • Statisch verknüpfte ausführbare Dateien
  • LOCAL_CLANG:=false Ziele
  • LOCAL_SANITIZE:=false werden für SANITIZE_TARGET=address nicht genehmigt

Ausführbare Dateien dieser Art werden im SANITIZE_TARGET-Build übersprungen und der Die Version vom ersten Aufruf wird in /system/bin beibehalten.

Solche Bibliotheken werden ohne ASan erstellt. Sie können ASan-Code aus den statischen Bibliotheken enthalten, von denen sie abhängen.

Zusätzliche Dokumentation