AddressSanitizer (ASan) è uno strumento rapido basato su compilatore per il rilevamento di memoria bug nel codice nativo.
ASan rileva:
- overflow/underflow del buffer di stack e heap
- Utilizzo dell'heap dopo la prova senza costi
- Utilizzo dello stack al di fuori dell'ambito
- Doppio/libero/selvaggio
ASan funziona su ARM a 32 e 64 bit, più x86 e x86-64. Overhead della CPU di ASan è di circa 2x, l'overhead per le dimensioni del codice è compreso tra il 50% e 2x e un overhead della memoria di grandi dimensioni (dipende dai pattern di allocazione, ma nell'ordine di 2 volte).
Android 10 e ramo principale di AOSP su AArch64 supportare AddressSanitizer con assistenza hardware (HWASan), uno strumento simile con un overhead di RAM più basso di bug rilevati. HWASan rileva l'uso dello stack dopo il reso, oltre ai bug rilevato da ASan.
HWASan ha un overhead simile a quello della CPU e del codice, ma un overhead della RAM molto inferiore (15%). HWASan non è deterministico. I possibili valori di tag sono solamente 256, perciò esiste un valore fisso pari allo 0,4% probabilità di mancare qualche bug. HWASan non ha zone rosse di dimensioni limitate di ASan per il rilevamento degli overflow e la quarantena a capacità limitata per rilevare l'uso a posteriori, quindi non importa per HWASan quanto sia grande l'overflow o quanto tempo fa è stato assegnato. Questo rende HWASan migliore di ASan. Puoi scoprire di più sulle dei contenuti HWASan o sull'utilizzo di HWASan su Android.
ASan rileva gli overflow dello stack/globali oltre agli overflow dell'heap ed è veloce con un overhead di memoria minimo.
Questo documento descrive come creare ed eseguire componenti/tutto Android con ASan Se stai creando un'app SDK/NDK con ASan, consulta Disinfettante per indirizzi .
Elimina singoli eseguibili con ASan
Aggiungi LOCAL_SANITIZE:=address
o sanitize: { address: true }
a
la regola di build per l'eseguibile. Puoi cercare nel codice esempi esistenti o trovare
gli altri disinfettanti disponibili.
Quando viene rilevato un bug, ASan stampa un report dettagliato sia sul server
e in logcat
, quindi il processo si arresta in modo anomalo.
Pulisci le librerie condivise con ASan
Per via del suo funzionamento, una libreria creata con ASan può essere utilizzata solo creato con ASan.
Per pulire una libreria condivisa utilizzata in più eseguibili, non tutti
create con ASan, sono necessarie due copie della libreria. La
il modo consigliato per farlo è aggiungere quanto segue a Android.mk
per il modulo in questione:
LOCAL_SANITIZE:=address LOCAL_MODULE_RELATIVE_PATH := asan
In questo modo la libreria viene posizionata in /system/lib/asan
anziché
/system/lib
. Poi esegui l'eseguibile con:
LD_LIBRARY_PATH=/system/lib/asan
Per i daemon di sistema, aggiungi quanto segue alla sezione appropriata di
/init.rc
o /init.$device$.rc
.
setenv LD_LIBRARY_PATH /system/lib/asan
Verifica che il processo utilizzi le librerie di /system/lib/asan
se presente, leggendo /proc/$PID/maps
. In caso contrario, potresti aver bisogno
per disattivare SELinux:
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.
Analisi dello stack migliori
ASan utilizza un unwinder veloce basato su frame pointer per registrare uno stack per ogni evento di allocazione della memoria e di dealcazione nel programma. Più alta di Android è realizzato senza i cursori dei frame. Di conseguenza, spesso ottieni solo uno o due frame significativi. Per risolvere il problema, ricrea la libreria con ASan (consigliato!) o con:
LOCAL_CFLAGS:=-fno-omit-frame-pointer LOCAL_ARM_MODE:=arm
Oppure imposta ASAN_OPTIONS=fast_unwind_on_malloc=0
durante la procedura
completamente gestito di Google Cloud. Quest'ultimo può utilizzare molta CPU, a seconda
al carico.
Simbolizzazione
Inizialmente, i report ASan contengono riferimenti agli offset nei file binari e librerie. Esistono due modi per ottenere informazioni sui file di origine e sulle righe:
- Assicurati che il programma binario
llvm-symbolizer
sia presente in/system/bin
.llvm-symbolizer
viene creato da origini inthird_party/llvm/tools/llvm-symbolizer
. - Filtra il report tramite il
external/compiler-rt/lib/asan/scripts/symbolize.py
lo script.
Il secondo approccio può fornire più dati (ossia file:line
località) grazie
la disponibilità di librerie simboliche sull'host.
ASan nelle app
ASan non può vedere il codice Java, ma può rilevare i bug nella JNI
librerie. Per farlo, devi creare l'eseguibile con ASan, che
questo caso è /system/bin/app_process(32|64)
. Questo
attiva ASan in tutte le app sul dispositivo contemporaneamente,
ma con 2 GB di RAM.
Aggiungi LOCAL_SANITIZE:=address
a
la regola di build app_process
in frameworks/base/cmds/app_process
. Ignora
per il momento il target app_process__asan
nello stesso file (se si tratta
ancora lì al momento in cui leggi questo documento).
Modifica la sezione service zygote
del
file system/core/rootdir/init.zygote(32|64).rc
appropriato per aggiungere
le righe seguenti al blocco di righe rientrate contenente class main
, anche
rientrato dello stesso valore:
setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib setenv ASAN_OPTIONS allow_user_segv_handler=true
Creazione, sincronizzazione adb, avvio flash fastboot e riavvio.
Utilizzare la proprietà wrap
L'approccio nella sezione precedente inserisce ASan in ogni app nel sistema (in realtà, in ogni discendente della ). È possibile eseguire solo una (o più) app con ASan, scambiando un carico di memoria per un avvio più lento dell'app.
A questo scopo, avvia l'app con la proprietà wrap.
.
Nell'esempio seguente viene eseguita l'app Gmail in ASan:
adb root
adb shell setenforce 0 # disable SELinux
adb shell setprop wrap.com.google.android.gm "asanwrapper"
In questo contesto, asanwrapper
riscrive /system/bin/app_process
a /system/bin/asan/app_process
, che è creato con
ASan Aggiunge anche /system/lib/asan
all'inizio di
il percorso di ricerca nella libreria dinamica. In questo modo ASan
le librerie di /system/lib/asan
sono preferite alle librerie normali
in /system/lib
se eseguita con asanwrapper
.
Se viene trovato un bug, l'app ha un arresto anomalo e la segnalazione viene stampata su nel log.
SANITIZZA_TARGET
Android 7.0 e versioni successive include il supporto per la creazione dell'intera piattaforma Android con ASan. Se stai sviluppando una release superiore ad Android 9, HWASan è una scelta migliore.
Esegui i comandi riportati di seguito nello stesso albero di build.
make -j42
SANITIZE_TARGET=address make -j42
In questa modalità, userdata.img
contiene librerie aggiuntive e deve essere
sul dispositivo. Utilizza la seguente riga di comando:
fastboot flash userdata && fastboot flashall
In questo modo vengono creati due insiemi di librerie condivise: normale in
/system/lib
(la prima chiamata di make) e strumenti ASan in
/data/asan/lib
(la seconda chiamata di make). Eseguibili dal
la seconda build sovrascriverà quelle della prima. Con strumentazione ASan
gli eseguibili ricevono un percorso di ricerca nella libreria diverso che include
/data/asan/lib
prima del giorno /system/lib
tramite l'uso di
/system/bin/linker_asan
a PT_INTERP
.
Il sistema di compilazione clona le directory degli oggetti intermedi quando
Il valore di $SANITIZE_TARGET
è stato modificato. Questa operazione forza la ricostruzione di tutti
sceglie come target mantenendo i file binari installati in /system/lib
.
Alcuni target non possono essere creati con ASan:
- Eseguibili collegati in modo statico
LOCAL_CLANG:=false
targetLOCAL_SANITIZE:=false
non soddisfano gli attributi ASan perSANITIZE_TARGET=address
Gli eseguibili come questi vengono ignorati nella build SANITIZE_TARGET
e
versione della prima chiamata di make viene lasciata in /system/bin
.
Librerie come questa vengono create senza ASan. Possono contenere alcuni ASan il codice dalle librerie statiche da cui dipendono.