AddressSanitizer (ASan) est un outil rapide basé sur un compilateur qui détecte les bugs de mémoire dans le code natif.
ASan détecte les bugs suivants :
- Débordement positif/négatif de la pile et du tampon de tas de mémoire
- Bugs "use-after-free" au niveau des tas de mémoire
- Utilisation de la pile en dehors du champ d'application
- Bugs de type "double free"/"wild free"
ASan fonctionne sur les versions ARM 32 bits et 64 bits, ainsi que sur x86 et x86-64. Surcharge du processeur d'ASan est d'environ 2 fois, la surcharge de la taille du code est comprise entre 50% et 2 fois supérieure, et une surcharge de mémoire importante (en fonction de vos schémas d'allocation, mais de l'ordre de 2x).
Android 10 et la branche principale d'AOSP sur AArch64 prendre en charge AddressSanitizer avec assistance matérielle (HWASan) ; un outil similaire avec une surcharge de RAM inférieure et un plus grand de bugs détectés. HWASan détecte l'utilisation de la pile après le retour, en plus des bugs détecté par ASan.
HWASan présente une surcharge de processeur et de taille de code similaire, mais une surcharge de RAM beaucoup plus faible (15%). HWASan n'est pas déterministe. Il n'y a que 256 valeurs de tag possibles, la valeur est donc plate de 0,4% la probabilité de manquer un bug. HWASan n'inclut pas de zones rouges de taille limitée ASan pour détecter les dépassements et les zones de quarantaine à capacité limitée pour détecter l'utilisation après libération, La taille du débordement ou l'ancienneté de la mémoire n'ont donc pas d'importance pour HWASan. a été désaffectée. C'est pourquoi HWASan est plus performant qu'ASan. Pour en savoir plus sur les HWASan ou à propos de l'utilisation de HWASan sur Android.
ASan détecte les dépassements de pile/global. en plus des dépassements de tas de mémoire, et est rapide avec une surcharge de mémoire minimale.
Ce document explique comment compiler et exécuter certaines parties/l'ensemble d'Android avec ASan Si vous créez une application SDK/NDK avec ASan, consultez Address Sanitizer à la place.
Nettoyer les exécutables individuels avec ASan
Ajouter LOCAL_SANITIZE:=address
ou sanitize: { address: true }
à
la règle de compilation de l'exécutable. Vous pouvez rechercher des exemples existants dans le code ou trouver
les autres désinfectants disponibles.
Lorsqu'un bug est détecté, ASan imprime un rapport de type "verbose" à la fois
de sortie et à logcat
, puis fait planter le processus.
Nettoyer les bibliothèques partagées avec ASan
En raison du fonctionnement d'ASan, une bibliothèque créée avec ASan ne peut être utilisée que créé avec ASan.
Pour nettoyer une bibliothèque partagée utilisée
dans plusieurs exécutables, pas tous
qui sont compilés avec ASan, vous avez besoin de deux exemplaires de la bibliothèque. La
Pour ce faire, il est recommandé 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
Exécutez ensuite le fichier exécutable avec la commande suivante:
LD_LIBRARY_PATH=/system/lib/asan
Pour les daemons système, ajoutez le code suivant à la section appropriée
/init.rc
ou /init.$device$.rc
.
setenv LD_LIBRARY_PATH /system/lib/asan
Vérifiez que le processus utilise des bibliothèques de /system/lib/asan
lorsqu'il est présent en lisant /proc/$PID/maps
. Si ce n'est pas le cas, vous devrez peut-être
pour 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.
Améliorer les traces de la pile
ASan utilise un dérouleur rapide basé sur un pointeur de frame pour enregistrer une pile une trace pour chaque événement d'allocation et de désallocation de mémoire dans le programme. La plupart d'Android est conçu sans pointeurs de frame. Par conséquent, vous obtenez souvent qu'un ou deux cadres significatifs. Pour résoudre ce problème, recréez 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
lors du processus
environnement. Le second peut nécessiter une utilisation intensive du processeur,
la charge.
Symbolisation
Au départ, les rapports ASan contiennent des références aux décalages dans les fichiers binaires et les fichiers partagés bibliothèques. 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 créé à partir de sources dansthird_party/llvm/tools/llvm-symbolizer
- Filtrez le rapport via
external/compiler-rt/lib/asan/scripts/symbolize.py
. script.
La deuxième méthode peut fournir plus de données (file:line
lieux) en raison des
la disponibilité des 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 bugs dans JNI
bibliothèques. Pour cela, vous devez compiler l'exécutable avec ASan, qui dans
ce cas est /system/bin/app_process(32|64)
. Ce
active ASan en même temps dans toutes les applications de l'appareil, ce qui
mais un appareil disposant de 2 Go de RAM devrait pouvoir gérer cela.
Ajouter LOCAL_SANITIZE:=address
à
la règle de compilation app_process
dans frameworks/base/cmds/app_process
. Ignorer
la cible app_process__asan
dans le même fichier pour le moment (s'il s'agit
toujours là au moment où vous lisez cet article).
Modifiez la section service zygote
de
le fichier system/core/rootdir/init.zygote(32|64).rc
approprié pour ajouter
les lignes suivantes au bloc de lignes en retrait contenant class main
, également
en retrait de la même quantité:
setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib setenv ASAN_OPTIONS allow_user_segv_handler=true
Build, synchronisation adb, démarrage flash fastboot et redémarrage.
Utiliser la propriété d'encapsulation
L'approche de la section précédente place ASan dans chaque dans le système (en fait, dans chaque descendant du système processus). Il est possible d'exécuter une seule (ou plusieurs) applications avec ASan, en évitant une surcharge de mémoire pour un démarrage plus lent de l'application.
Pour ce faire, démarrez votre application avec la propriété wrap.
.
L'exemple suivant permet d'exécuter 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
.
à /system/bin/asan/app_process
, qui repose sur
ASan Elle ajoute également /system/lib/asan
au début de
le chemin de recherche dynamique
dans la bibliothèque. Instrumentée par ASan,
Les bibliothèques de /system/lib/asan
sont préférées aux bibliothèques normales
dans /system/lib
lors de l'exécution avec asanwrapper
.
Si un bug est détecté, l'application plante et le rapport est imprimé sur dans le journal.
SANITIZE_TARGET
Android 7.0 et versions ultérieures permettent de créer l'intégralité de la plate-forme Android avec ASan en même temps. (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 compilation.
make -j42
SANITIZE_TARGET=address make -j42
Dans ce mode, userdata.img
contient des bibliothèques supplémentaires et doit être
flashé sur l'appareil également. Utilisez la ligne de commande suivante:
fastboot flash userdata && fastboot flashall
Cela crée deux ensembles de bibliothèques partagées: normal dans
/system/lib
(le premier appel de la méthode make) et instrumenté par ASan dans
/data/asan/lib
(deuxième appel de la création). Les exécutables
la deuxième compilation écrase
celles de la première compilation. Instrumentée par ASan
exécutables reçoivent un chemin de recherche
de bibliothèque différent qui inclut
/data/asan/lib
avant /system/lib
grâce à l'utilisation de
/system/bin/linker_asan
dans PT_INTERP
.
Le système de compilation enlève les répertoires d'objets intermédiaires lorsque
La valeur de $SANITIZE_TARGET
a changé. Cela impose une reconstruction de tous
tout en conservant les binaires installés sous /system/lib
.
Certaines cibles ne peuvent pas être créées avec ASan:
- Exécutables associés de manière statique
LOCAL_CLANG:=false
ciblesLOCAL_SANITIZE:=false
ne sont pas reconnus par ASan pourSANITIZE_TARGET=address
Les fichiers exécutables de ce type sont ignorés dans le build SANITIZE_TARGET
, et
du premier appel de création reste dans /system/bin
.
Les bibliothèques de ce type sont construites sans ASan. Ils peuvent contenir des ASan du code des bibliothèques statiques dont elles dépendent.