AddressSanitizer

AddressSanitizer (ASan) ist ein schnelles Compiler-basiertes Tool zur Erkennung in nativem Code nicht so schnell wie möglich.

ASan erkennt:

  • Überlauf/Unterlauf für Stack- und Heap-Zwischenspeicher
  • Heap-Nutzung nach kostenloser Nutzung
  • Stack-Verwendung außerhalb des Zuständigkeitsbereichs
  • Doppeltes Freibad/Wildtreffer

ASan wird sowohl auf 32-Bit- als auch auf 64-Bit-ARM sowie x86 und x86-64 ausgeführt. CPU-Overhead von ASan ungefähr doppelt so hoch, der Codegrößen-Overhead liegt zwischen 50 und 2-mal (abhängig von Ihren Zuweisungsmustern, aber in einer Größenordnung von 2x).

Android 10 und der AOSP-Hauptzweig auf AArch64 Hardware-Assisted AddressSanitizer (HWASan) unterstützt ein ähnliches Tool mit geringerem RAM-Overhead und der gefundenen Fehler. HWASan erkennt die Stack-Nutzung nach der Rückgabe sowie die Fehler die von ASan erkannt wurden.

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. Dies macht HWASan besser als ASan. Weitere Informationen zu den Design von HWASan oder zur Verwendung von HWASan unter Android

ASan erkennt Stack-/globale Überläufe und Heap-Overflows und ist bei minimalem Arbeitsspeicher-Overhead schnell.

In diesem Dokument wird beschrieben, wie Sie Android mit San Francisco. Wenn Sie eine SDK/NDK-App mit ASan erstellen, lesen Sie Adressbereinigung .

Einzelne ausführbare Dateien mit ASan bereinigen

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

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 Bibliothek, die mit ASan gebaut wurde, nur von einem ausführbare Datei, die mit ASan erstellt wurde.

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

LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

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

LD_LIBRARY_PATH=/system/lib/asan

Für System-Daemons fügen Sie im entsprechenden Abschnitt /init.rc oder /init.$device$.rc.

setenv LD_LIBRARY_PATH /system/lib/asan

Prüfen Sie, ob der Prozess Bibliotheken von /system/lib/asan verwendet wenn vorhanden, indem /proc/$PID/maps gelesen wird. 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. Das führt dazu, dass nur ein oder zwei sinnvolle 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

Oder ASAN_OPTIONS=fast_unwind_on_malloc=0 während des Vorgangs festlegen zu verbessern. Letztere kann sehr CPU-intensiv sein, je nachdem, die Last.

Symbolisierung

Anfangs enthalten ASan-Berichte Verweise auf Offsets in Binärdateien und freigegebene Bibliotheken. Es gibt zwei Möglichkeiten, Informationen zu Quelldatei und -zeile abzurufen:

  • Die Binärdatei llvm-symbolizer muss in /system/bin vorhanden sein. llvm-symbolizer basiert auf Quellen in third_party/llvm/tools/llvm-symbolizer.
  • Bericht nach external/compiler-rt/lib/asan/scripts/symbolize.py filtern .

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, die in dieser Fall ist /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.

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

Bearbeiten Sie den Abschnitt service zygote des entsprechende system/core/rootdir/init.zygote(32|64).rc-Datei zum bis zum Block eingerückter Zeilen mit class main folgen, sowie um den gleichen Betrag eingerückt:

    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 den Arbeitsspeicher-Aufwand gegen einen langsameren Start der App.

Starte dazu deine App mit der Property wrap.. 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 Kontext schreibt asanwrapper /system/bin/app_process um an /system/bin/asan/app_process, das mit San Francisco. Außerdem wird /system/lib/asan am Anfang von dynamischen Bibliothekssuchpfad hinzu. Auf diese Weise instrumentierte ASan Bibliotheken aus /system/lib/asan werden normalen Bibliotheken vorgezogen in /system/lib bei Ausführung mit asanwrapper.

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

SANITIZE_TARGET

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 auf das Gerät geflasht haben. Verwenden Sie die folgende Befehlszeile:

fastboot flash userdata && fastboot flashall

Dadurch werden zwei Sätze gemeinsam genutzter Bibliotheken erstellt: normal in /system/lib (der erste Aufruf) und ASan-instrumentiert in /data/asan/lib (der zweite Make-Aufruf). Ausführbare Dateien aus dem des ersten Builds überschreiben. ASan-instrumentiert ausführbaren Dateien erhalten einen anderen Bibliothekssuchpfad, der Folgendes enthält: /data/asan/lib vor dem /system/lib durch die Verwendung von „/system/bin/linker_asan“ in „PT_INTERP“.

Das Build-System clobbers sperrt Zwischenobjektverzeichnisse, wenn der Der Wert von „$SANITIZE_TARGET“ hat sich geändert. Dadurch wird eine Neuerstellung aller Ziele unter Beibehaltung installierter Binärdateien unter /system/lib beibehalten.

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 wie diese werden im Build SANITIZE_TARGET übersprungen und der Die Version vom ersten Aufruf wird in /system/bin beibehalten.

Bibliotheken wie diese werden ohne ASan erstellt. Sie können einige ASan enthalten. Code aus den statischen Bibliotheken, von denen sie abhängig sind.

Zusätzliche Dokumentation