Google is committed to advancing racial equity for Black communities. See how.
Cette page a été traduite par l'API Cloud Translation.
Switch to English

AdresseSanitizer

AddressSanitizer (ASan) est un outil rapide basé sur un compilateur pour détecter les bogues de mémoire dans le code natif.

ASan détecte:

  • Dépassement / sous-dépassement de la mémoire tampon de la pile et du tas
  • Utilisation du tas après gratuit
  • Utilisation de la pile en dehors de la portée
  • Double libre / sauvage gratuit

ASan fonctionne à la fois sur ARM 32 bits et 64 bits, plus x86 et x86-64. La surcharge du processeur d'ASan est d'environ 2x, la surcharge de la taille du code est comprise entre 50% et 2x, et une surcharge de mémoire importante (dépend de vos modèles d'allocation, mais de l'ordre de 2x).

Android 10 et la branche principale AOSP sur AArch64 prennent en charge ASan à accélération matérielle (HWASan) , un outil similaire avec une charge RAM inférieure et une plus grande gamme de bogues détectés. HWASan détecte l'utilisation de la pile après le retour, en plus des bogues détectés par ASan.

HWASan a une surcharge de CPU et de taille de code similaire, mais une surcharge de RAM beaucoup plus petite (15%). HWASan est non déterministe. Il n'y a que 256 valeurs de balises possibles, il y a donc une probabilité plate de 0,4% de manquer un bogue. HWASan ne dispose pas de zones rouges de taille limitée d'ASan pour détecter les débordements et d'une quarantaine de capacité limitée pour détecter l'utilisation après la libération, donc peu importe pour HWASan l'ampleur du débordement ou depuis combien de temps la mémoire a été désallouée. Cela rend HWASan meilleur que ASan. Vous pouvez en savoir plus sur la conception de HWASan ou sur l'utilisation de HWASan sur Android .

ASan détecte les débordements de pile / globaux en plus des débordements de tas, et est rapide avec une surcharge de mémoire minimale.

Ce document décrit comment créer et exécuter des parties / l'ensemble d'Android avec ASan. Si vous créez une application SDK / NDK avec ASan, consultez plutôt Address Sanitizer .

Désinfection des exécutables individuels avec ASan

Ajoutez LOCAL_SANITIZE:=address ou sanitize: { address: true } à la règle de construction pour l'exécutable. Vous pouvez rechercher dans le code des exemples existants ou trouver les autres désinfectants disponibles.

Lorsqu'un bogue est détecté, ASan imprime un rapport détaillé à la fois sur la sortie standard et dans logcat , puis bloque le processus.

Désinfection des bibliothèques partagées avec ASan

En raison de la façon dont fonctionne ASan, une bibliothèque construite avec ASan ne peut être utilisée que par un exécutable construit avec ASan.

Pour nettoyer une bibliothèque partagée utilisée dans plusieurs exécutables, qui ne sont pas tous construits avec ASan, vous avez besoin de deux copies de la bibliothèque. La méthode recommandée pour ce faire est d'ajouter ce qui suit à Android.mk pour le module en question:

LOCAL_SANITIZE:=address
LOCAL_MODULE_RELATIVE_PATH := asan

Cela place la bibliothèque dans /system/lib/asan au lieu de /system/lib . Ensuite, exécutez votre exécutable avec:

LD_LIBRARY_PATH=/system/lib/asan

Pour les démons système, ajoutez ce qui suit à la section appropriée de /init.rc ou /init.$device$.rc .

setenv LD_LIBRARY_PATH /system/lib/asan

Vérifiez que le processus utilise les bibliothèques de /system/lib/asan lorsqu'elle est présente en lisant /proc/$PID/maps . Si ce n'est pas le cas, vous devrez peut-être désactiver 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.

Meilleures traces de pile

ASan utilise un dérouleur rapide basé sur un pointeur de trame pour enregistrer une trace de pile pour chaque événement d'allocation de mémoire et de désallocation dans le programme. La plupart d'Android est construit sans pointeurs d'image. En conséquence, vous n'obtenez souvent qu'une ou deux images significatives. Pour résoudre ce problème, reconstruisez la bibliothèque avec ASan (recommandé!), Ou avec:

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

Ou définissez ASAN_OPTIONS=fast_unwind_on_malloc=0 dans l'environnement de processus. Ce dernier peut être très gourmand en CPU, en fonction de la charge.

Symbolisation

Au départ, les rapports ASan contiennent des références aux décalages dans les binaires et les bibliothèques partagées. Il existe deux façons d'obtenir des informations sur le fichier source et la ligne:

  • Assurez-vous que le binaire llvm-symbolizer est présent dans /system/bin . llvm-symbolizer est construit à partir des sources de third_party/llvm/tools/llvm-symbolizer .
  • Filtrez le rapport via le script external/compiler-rt/lib/asan/scripts/symbolize.py .

La deuxième approche peut fournir plus de données (c'est-à-dire file:line emplacements de file:line ) en raison de la disponibilité de bibliothèques symbolisées sur l'hôte.

ASan dans les applications

ASan ne peut pas voir dans le code Java, mais il peut détecter des bogues dans les bibliothèques JNI. Pour cela, vous devez construire l'exécutable avec ASan, qui dans ce cas est /system/bin/app_process( 32|64 ) . Cela permet à ASan dans toutes les applications de l'appareil en même temps, ce qui est une charge lourde, mais un appareil avec 2 Go de RAM devrait être capable de gérer cela.

Ajoutez LOCAL_SANITIZE:=address à la règle de génération app_process dans frameworks/base/cmds/app_process . Ignorez la cible app_process__asan dans le même fichier pour le moment (si elle est toujours là au moment où vous lisez ceci).

Modifiez la section service zygote du fichier system/core/rootdir/init.zygote( 32|64 ).rc approprié pour ajouter les lignes suivantes au bloc de lignes en retrait contenant la class main , également en retrait du même montant:

    setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib
    setenv ASAN_OPTIONS allow_user_segv_handler=true

Compilation, synchronisation adb, démarrage rapide du flash et redémarrage.

Utilisation de la propriété wrap

L'approche de la section précédente place ASan dans chaque application du système (en fait, dans chaque descendant du processus Zygote). Il est possible d'exécuter une seule (ou plusieurs) applications avec ASan, en échangeant une surcharge de mémoire pour un démarrage plus lent de l'application.

Cela peut être fait en démarrant votre application avec le wrap. propriété. L'exemple suivant exécute l'application Gmail sous ASan:

adb root
adb shell setenforce 0  # disable SELinux
adb shell setprop wrap.com.google.android.gm "asanwrapper"

Dans ce contexte, asanwrapper réécrit /system/bin/app_process en /system/bin/asan/app_process , qui est construit avec ASan. Il ajoute également /system/lib/asan au début du chemin de recherche dynamique de la bibliothèque. De cette façon, les bibliothèques instrumentées par ASan depuis /system/lib/asan sont préférées aux bibliothèques normales dans /system/lib lors de l'exécution avec asanwrapper .

Si un bogue est détecté, l'application se bloque et le rapport est imprimé dans le journal.

SANITIZE_TARGET

Android 7.0 et supérieur inclut la prise en charge de la création simultanée de l'ensemble de la plate-forme Android avec ASan. (Si vous créez une version supérieure à Android 9, HWASan est un meilleur choix.)

Exécutez les commandes suivantes dans la même arborescence de construction.

make -j42
SANITIZE_TARGET=address make -j42

Dans ce mode, userdata.img contient des bibliothèques supplémentaires et doit également être flashé sur le périphérique. Utilisez la ligne de commande suivante:

fastboot flash userdata && fastboot flashall

Cela construit deux ensembles de bibliothèques partagées: normal dans /system/lib (le premier appel make), et ASan-instrumenté dans /data/asan/lib (le second make invocation). Les exécutables de la deuxième version écrasent ceux de la première version. Les exécutables instrumentés par ASan obtiennent un chemin de recherche de bibliothèque différent qui inclut /data/asan/lib avant /system/lib via l'utilisation de /system/bin/linker_asan dans PT_INTERP .

Le système de construction écrase les répertoires d'objets intermédiaires lorsque la valeur $SANITIZE_TARGET a changé. Cela force une reconstruction de toutes les cibles tout en préservant les binaires installés sous /system/lib .

Certaines cibles ne peuvent pas être construites avec ASan:

  • Exécutables liés statiquement
  • LOCAL_CLANG:=false cibles
  • LOCAL_SANITIZE:=false n'est pas ASan'd pour SANITIZE_TARGET=address

Les exécutables comme ceux-ci sont ignorés dans la construction SANITIZE_TARGET , et la version de la première invocation de make est laissée dans /system/bin .

Les bibliothèques comme celle-ci sont construites sans ASan. Ils peuvent contenir du code ASan des bibliothèques statiques dont ils dépendent.

Documentation à l'appui