Igienizzante indirizzi

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.

  1. Aggiungi android:debuggable al file manifest dell'applicazione.
  2. Imposta useLegacyPackaging a true nel file build.gradle dell'app. Consulta la guida relativa allo script shell a capo per ulteriori informazioni.
  3. Aggiungi la libreria di runtime ASan al valore jniLibs del modulo dell'app.
  4. Aggiungi file wrap.sh con i seguenti contenuti a ogni directory nella cartella Directory src/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
    "$@"
    
di Gemini Advanced.

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:

  1. Un "rapido" di svolgimento basato su puntatore frame. È ciò che viene utilizzato seguendo le nella sezione dedicata agli edifici.

  2. 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.