Android NDK supporta il sanitizer degli indirizzi (noto anche come ASan) a partire da con il livello API 27 (Android O MR 1).
ASan è uno strumento basato su un compilatore rapido per rilevare i bug di memoria 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
L'overhead della CPU di ASan è di circa 2 volte, l'overhead della dimensione del codice è compreso tra il 50% e il 2x, e l'overhead della memoria è elevato (dipende dai pattern di allocazione, ma nell'ordine di 2x).
App di esempio
Un'app di esempio mostra come configurare una variante di build per asan.
Crea
Per creare il codice nativo della tua app (JNI) con Address Sanitizer, procedi nel seguente modo: seguenti:
build-ndk
In Application.mk:
APP_STL := c++_shared # Or system, or none.
APP_CFLAGS := -fsanitize=address -fno-omit-frame-pointer
APP_LDFLAGS := -fsanitize=address
Per ogni modulo nel file Android.mk:
LOCAL_ARM_MODE := arm
Marca
Nel file build.gradle del tuo modulo:
android {
defaultConfig {
externalNativeBuild {
cmake {
// Can also use system or none as ANDROID_STL.
arguments "-DANDROID_ARM_MODE=arm", "-DANDROID_STL=c++_shared"
}
}
}
}
Per ogni target nel file CMakeLists.txt:
target_compile_options(${TARGET} PUBLIC -fsanitize=address -fno-omit-frame-pointer)
set_target_properties(${TARGET} PROPERTIES LINK_FLAGS -fsanitize=address)
Esegui
A partire da Android O MR1 (livello API 27), un'applicazione può fornire un script shell a capo che può aggregare o sostituire il processo dell'applicazione. Ciò consente di cui è possibile eseguire il debug per personalizzare l'avvio, utilizzando ASan sui dispositivi di produzione.
- Aggiungi
android:debuggable
al file manifest dell'applicazione. - Imposta
useLegacyPackaging
atrue
nel filebuild.gradle
dell'app. Consulta la guida relativa allo script shell a capo per ulteriori informazioni. - Aggiungi la libreria di runtime ASan al valore
jniLibs
del modulo dell'app. Aggiungi file
wrap.sh
con i seguenti contenuti a ogni directory nella cartella Directorysrc/main/resources/lib
.#!/system/bin/sh HERE="$(cd "$(dirname "$0")" && pwd)" export ASAN_OPTIONS=log_to_syslog=false,allow_user_segv_handler=1 ASAN_LIB=$(ls $HERE/libclang_rt.asan-*-android.so) if [ -f "$HERE/libc++_shared.so" ]; then # Workaround for https://github.com/android-ndk/ndk/issues/988. export LD_PRELOAD="$ASAN_LIB $HERE/libc++_shared.so" else export LD_PRELOAD="$ASAN_LIB" fi "$@"
Supponendo che il modulo dell'applicazione del tuo progetto sia denominato app
, la tua directory finale
dovrebbe includere quanto segue:
<project root>
└── app
└── src
└── main
├── jniLibs
│ ├── arm64-v8a
│ │ └── libclang_rt.asan-aarch64-android.so
│ ├── armeabi-v7a
│ │ └── libclang_rt.asan-arm-android.so
│ ├── x86
│ │ └── libclang_rt.asan-i686-android.so
│ └── x86_64
│ └── libclang_rt.asan-x86_64-android.so
└── resources
└── lib
├── arm64-v8a
│ └── wrap.sh
├── armeabi-v7a
│ └── wrap.sh
├── x86
│ └── wrap.sh
└── x86_64
└── wrap.sh
Analisi dello stack
Il disinfettante degli indirizzi deve snellire la pila ogni malloc
/realloc
/free
chiamata. Le opzioni sono due:
Un "rapido" di svolgimento basato su puntatore frame. È ciò che viene utilizzato seguendo le nella sezione dedicata agli edifici.
Un approccio "lenta" Svolgitore CFI. In questa modalità, ASan utilizza
_Unwind_Backtrace
. it richiede solo-funwind-tables
, che normalmente è abilitato per impostazione predefinita.
Lo strumento di svolgimento rapido è l'impostazione predefinita per Malloc/realloc/free. La funzionalità di rilassamento lenta è
è l'impostazione predefinita
per le analisi dello stack irreversibili. Lo svolgimento lento può essere abilitato per tutti
analisi dello stack aggiungendo fast_unwind_on_malloc=0
alla variabile ASAN_OPTIONS
nel file wrap.sh.