AdresseDesinfektionsmittel

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

ASan erkennt:

  • Stack- und Heap-Pufferüberlauf/-unterlauf
  • Heap-Nutzung nach kostenlos
  • Stapelverwendung außerhalb des Geltungsbereichs
  • Doppelzimmer frei/wild frei

ASan läuft sowohl auf 32-Bit- als auch auf 64-Bit-ARM sowie auf x86 und x86-64. Der CPU-Overhead von ASan beträgt ungefähr das 2-fache, der Codegrößen-Overhead liegt zwischen 50% und 2x und ein großer Speicher-Overhead (abhängig von Ihren Zuordnungsmustern, aber in der Größenordnung von 2x).

Android 10 und der Master - Zweig auf AOSP AArch64 Unterstützung hardwarebeschleunigtem ASAN (Hwasan) , ein ähnliches Werkzeug mit unterem RAM - Overhead und einem größeren Bereich der erkannten Fehler. HWASan erkennt die Stack-Nutzung nach der Rückgabe zusätzlich zu den von ASan erkannten Fehlern.

HWASa hat einen ähnlichen CPU- und Codegrößen-Overhead, aber einen viel geringeren RAM-Overhead (15%). HWASa ist nichtdeterministisch. Es gibt nur 256 mögliche Tag-Werte, daher besteht eine pauschale Wahrscheinlichkeit von 0,4%, einen Fehler zu übersehen. HWASan verfügt nicht über die begrenzten roten Zonen von ASan zum Erkennen von Überläufen und die Quarantäne mit begrenzter Kapazität zum Erkennen von Verwendung nach freier Nutzung, daher spielt es für HWASan keine Rolle, wie groß der Überlauf ist oder wie lange es her ist, dass der Speicher freigegeben wurde. Dadurch ist HWASa besser als ASa. Sie können mehr über das lesen Design von Hwasan oder über den Einsatz von Hwasan auf Android .

ASan erkennt neben Heap-Überläufen auch Stapel-/Global-Überläufe und ist schnell mit minimalem Speicher-Overhead.

In diesem Dokument wird beschrieben, wie Sie Teile/das gesamte Android mit ASan erstellen und ausführen. Wenn Sie ein SDK / NDK App mit Asan Gebäude sind, siehe Adresse Sanitizer statt.

Bereinigung einzelner ausführbarer Dateien mit ASan

In LOCAL_SANITIZE:=address oder sanitize: { address: true } auf die Erstellungsregel für die ausführbare Datei. Sie können den Code nach vorhandenen Beispielen durchsuchen oder nach anderen verfügbaren Desinfektionsmitteln suchen.

Wenn ein Fehler erkannt wird, druckt Asan eine ausführliche sowohl an die Standardausgabe zu berichten und zu logcat und stürzt dann den Prozess.

Bereinigung gemeinsam genutzter Bibliotheken mit ASan

Aufgrund der Funktionsweise von ASan kann eine mit ASan erstellte Bibliothek nur von einer ausführbaren Datei verwendet werden, die mit ASan erstellt wurde.

Um eine gemeinsam genutzte Bibliothek zu bereinigen, die in mehreren ausführbaren Dateien verwendet wird, die nicht alle mit ASan erstellt wurden, benötigen Sie zwei Kopien der Bibliothek. Der empfohlene Weg , dies zu tun ist , um Folgendes hinzuzufügen Android.mk für das Modul in Frage:

LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

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

LD_LIBRARY_PATH=/system/lib/asan

Für System - Daemons, die folgende in den entsprechenden Abschnitten von hinzufügen /init.rc oder /init.$device$.rc .

setenv LD_LIBRARY_PATH /system/lib/asan

Stellen Sie sicher , dass der Prozess unter Verwendung von Bibliotheken aus /system/lib/asan wenn vorhanden durch Lese /proc/$PID/maps . Wenn dies nicht der Fall ist, müssen Sie möglicherweise SELinux 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 Stapelspuren

ASan verwendet einen schnellen, auf Frame-Zeigern basierenden Abwickler, um einen Stack-Trace für jedes Speicherzuweisungs- und Freigabeereignis im Programm aufzuzeichnen. Der Großteil von Android ist ohne Frame-Zeiger aufgebaut. Als Ergebnis erhalten Sie oft nur ein oder zwei aussagekräftige Frames. Um dies zu beheben, erstellen Sie die Bibliothek entweder mit ASan neu (empfohlen!) oder mit:

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

Oder setzen Sie ASAN_OPTIONS=fast_unwind_on_malloc=0 in der Prozessumgebung. Letzteres kann je nach Auslastung sehr CPU-intensiv sein.

Symbolisierung

Anfänglich enthalten ASa-Berichte Verweise auf Offsets in Binärdateien und gemeinsam genutzten Bibliotheken. Es gibt zwei Möglichkeiten, Quelldatei- und Zeileninformationen zu erhalten:

  • Stellen Sie sicher , dass die llvm-symbolizer binären in vorhanden ist /system/bin . llvm-symbolizer wird in von den Quellen gebaut third_party/llvm/tools/llvm-symbolizer .
  • Filtern Sie den Bericht über den external/compiler-rt/lib/asan/scripts/symbolize.py Skript.

Der zweite Ansatz kann mehr Daten zur Verfügung stellen (dh, file:line Standorte) wegen der Verfügbarkeit von symbolisierte Bibliotheken auf dem Host.

ASan in Apps

ASan kann Java-Code nicht einsehen, aber Fehler in den JNI-Bibliotheken erkennen. Dafür müssen Sie die ausführbare Datei mit Asan, die in diesem Fall bauen /system/bin/app_process( 32|64 ) . Dadurch wird ASan in allen Apps auf dem Gerät gleichzeitig aktiviert, was eine schwere Last ist, aber ein Gerät mit 2 GB RAM sollte dies bewältigen können.

In LOCAL_SANITIZE:=address an die app_process Erstellungsregel in frameworks/base/cmds/app_process . Ignorieren Sie die app_process__asan Ziel in der gleichen Datei jetzt (wenn es an der Zeit ist immer noch da Sie dies lesen).

Bearbeiten der service zygote Abschnitt des entsprechenden system/core/rootdir/init.zygote( 32|64 ).rc - Datei die folgenden Zeilen in dem Block der eingekerbten Linien enthält , hinzuzufügen class main , ebenfalls um den gleichen Betrag eingekerbt:

    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.

Verwenden der Wrap-Eigenschaft

Der Ansatz im vorherigen Abschnitt fügt ASan in jede App im System ein (eigentlich in jeden Nachkommen des Zygote-Prozesses). Es ist möglich, mit ASan nur eine (oder mehrere) Apps auszuführen, wobei ein gewisser Speicheraufwand gegen einen langsameren App-Start eingetauscht wird.

Dies kann durch das Starten der App mit dem getan werden wrap. Eigentum. 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 asanwrapper Schreibungen /system/bin/app_process zu /system/bin/asan/app_process , die mit Asan gebaut wird. Es fügt auch /system/lib/asan zu Beginn des dynamischen Bibliothekssuchpfades. Auf diese Weise Asan-instrumentierten Bibliotheken aus /system/lib/asan sind in den normalen Bibliotheken bevorzugt /system/lib , wenn bei laufenden asanwrapper .

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

SANITIZE_TARGET

Android 7.0 und höher unterstützt die gleichzeitige Erstellung der gesamten Android-Plattform mit ASan. (Wenn Sie eine Version höher als Android 9 erstellen, 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 userdata.img enthält zusätzliche Bibliotheken und muss auch an das Gerät geflasht werden. Verwenden Sie die folgende Befehlszeile:

fastboot flash userdata && fastboot flashall

Dies baut zwei Sätze von gemeinsam benutzten Bibliotheken: normal in /system/lib (der erste Aufruf make) und ASAN-instrumentierte in /data/asan/lib (der zweiten make Aufruf). Ausführbare Dateien aus dem zweiten Build überschreiben diejenigen aus dem ersten Build. Asan-instrumentierten ausführbare Dateien bekommen einen anderen Bibliothekssuchpfad, die folgenden beinhaltet /data/asan/lib vor /system/lib durch die Verwendung von /system/bin/linker_asan in PT_INTERP .

Die Build - System clobbers Zwischenobjektverzeichnisse , wenn der $SANITIZE_TARGET Wert hat sich geändert. Dies zwingt einen Umbau aller Ziele während installierten Binärdateien Konservieren unter /system/lib .

Einige Ziele können nicht mit ASAN erstellt werden:

  • Statisch verknüpfte ausführbare Dateien
  • LOCAL_CLANG:=false Ziele
  • LOCAL_SANITIZE:=false sind nicht ASan'd für SANITIZE_TARGET=address W SANITIZE_TARGET=address

Executables wie diese wird in der übersprungenen SANITIZE_TARGET zu bauen, und die Version von dem ersten Make - Aufruf wird in links /system/bin .

Bibliotheken wie diese werden ohne ASAN erstellt. Sie können ASa-Code aus den statischen Bibliotheken enthalten, von denen sie abhängen.

Unterstützende Dokumentation