Comprendre les rapports HWASan

Lorsque l'outil HWASan détecte un bug de mémoire, le processus est arrêté avec abort(), et un rapport est imprimé dans stderr et logcat. Comme tous les plantages natifs sur Android, les erreurs HWASan sont sous /data/tombstones.

Exemple de rapport

Par rapport aux plantages natifs normaux, HWASan contient des informations supplémentaires dans le champ Message d'abandon situé en haut de la pierre tombale. Voici un exemple de plantage basé sur la pile. Pour les bugs de pile, consultez la note concernant les sections spécifiques à la pile.

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/flame_hwasan/flame:Tiramisu/MASTER/7956676:userdebug/dev-keys'
Revision: 'DVT1.0'
ABI: 'arm64'
Timestamp: 2019-04-24 01:13:22+0000
pid: 11154, tid: 11154, name: sensors@1.0-ser  >>> /vendor/bin/hw/android.hardware.sensors@1.0-service <<<
signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr --------
Abort message: '

[...]

[0x00433ae20040,0x00433ae20060) is a small unallocated heap chunk; size: 32 offset: 5








[ … regular crash dump follows …]

Il s'agit d'un rapport semblable à celui d'AddressSanitizer. Contrairement à ces erreurs, presque tous les bugs HWASan sont des erreurs de non-correspondance de balise, c'est-à-dire un accès à la mémoire où une balise de pointeur ne correspond pas à la balise de mémoire correspondante. Il peut s'agir de l'un des éléments suivants:

  • Accès hors limites sur la pile ou la mémoire tampon
  • Erreur "use-after-free" sur le tas de mémoire
  • Erreur d'utilisation après le retour sur la pile

Sections

Vous trouverez ci-dessous une explication de chacune des sections du rapport HWASan.

Erreur d'accès

Contient des informations sur l'accès incorrect à la mémoire, y compris les éléments suivants:

  • Type d'accès (READ par rapport à WRITE)
  • Taille de l'accès (nombre d'octets auxquels une tentative d'accès a été effectuée)
  • Numéro de thread de l'accès
  • Balise de pointeur et de mémoire (pour le débogage avancé)

Accéder à la trace de la pile

Trace de la pile de l'accès incorrect à la mémoire. Consultez Symbolisation pour en savoir plus.

Cause

Cause potentielle de l'accès incorrect. Si plusieurs candidats sont proposés, ils sont listés par ordre de probabilité décroissante. Précède les informations détaillées sur la cause potentielle. HWASan peut diagnostiquer les causes suivantes:

  • Utilisation après libération
  • Différence de balise de pile, qui peut être une utilisation de la pile après le retour, une utilisation de la pile après le champ d'application ou une sortie du champ d'application
  • Dépassement de la mémoire tampon du tas de mémoire
  • Dépassement global

Informations sur la mémoire

Décrit ce que HWASan sait sur la mémoire à laquelle il accède et peut varier en fonction du type d'erreur:

Type de bug Cause Format du rapport
Non-correspondance de tags Utilisation après libération Utilisez le format de rapport suivant:
<address> is located N bytes inside of M-byte region [<start>, <end>)
freed by thread T0 here:
Dépassement de la mémoire tampon du tas de mémoire Notez qu'il peut également s'agir d'un sous-dépassement.
<address> is located N bytes to the right of M-byte region [<start>, <end>)
allocated here:
Incompatibilité de la balise de pile Les rapports sur la pile ne font pas la distinction entre les erreurs de débordement ou de sous-dépassement et les bugs d'utilisation après retour. De plus, pour trouver l'allocation de pile à l'origine de l'erreur, une étape de symbolisation hors connexion est requise. Consultez Comprendre les rapports de pile.
Espace libre non valide Utilisation après libération Bug de type "double free". Si cela se produit lors de l'arrêt du processus, cela peut indiquer une violation du règlement sur le règlement des litiges en ligne.
<address> is located N bytes inside of M-byte region [<start>, <end>)
freed by thread T0 here:
Impossible de décrire l'adresse Libération incontrôlée (libération de mémoire qui n'avait pas été allouée auparavant) ou double libération après que la mémoire allouée a été supprimée du tampon de libération de HWASan.
0x... correspond à la mémoire d'ombre HWAsan. Libération incontrôlée, car l'application tentait de libérer de la mémoire interne à HWASan.

Trace de la pile de désallocation

Trace de la pile de l'endroit où la mémoire a été désallouée. Présent uniquement pour les bugs d'utilisation après libération ou de valeur non valide. Pour symboliser, consultez Symbolisation.

Trace de la pile d'allocation

Trace de la pile de l'emplacement où la mémoire a été allouée. Pour symboliser, consultez Symbolisation.

Informations de débogage avancées

Le rapport HWASan contient également des informations de débogage avancées, y compris (par ordre):

  1. Liste des threads du processus
  2. Liste des threads du processus
  3. Valeur des tags de mémoire à proximité de la mémoire défaillante
  4. Dump des registres au point d'accès à la mémoire

Vidage de la balise de mémoire

Vous pouvez utiliser le vidage de mémoire de la balise pour rechercher des allocations de mémoire à proximité avec la même balise que la balise du pointeur. Ces balises peuvent indiquer un accès hors limites avec un décalage important. Une balise correspond à 16 octets de mémoire. La balise de pointeur correspond aux 8 premiers bits de l'adresse. Le vidage de mémoire de la balise peut fournir des indices. Par exemple, voici un débordement de tampon à droite:

tags: ad/5c (ptr/mem)
[...]
Memory tags around the buggy address (one tag corresponds to 16 bytes):
  0x006f33ae1ff0: 0e  0e  0e  57  20  20  20  20  20  2e  5e  5e  5e  5e  5e  b5
=>0x006f33ae2000: f6  f6  f6  f6  f6  4c  ad  ad  ad  ad  ad  ad [5c] 5c  5c  5c
  0x006f33ae2010: 5c  04  2e  2e  2e  2e  2e  2f  66  66  66  66  66  80  6a  6a
Tags for short granules around the buggy address (one tag corresponds to 16 bytes):
  0x006f33ae1ff0: ab  52  eb  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
=>0x006f33ae2000: ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  .. [..] ..  ..  ..
  0x006f33ae2010: ..  5c  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..

Notez la séquence de 6 × 16 = 96 octets de balises ad à gauche qui correspondent à la balise de pointeur.

Si la taille d'une allocation n'est pas un multiple de 16, le reste de la taille est stocké en tant que balise de mémoire et la balise est stockée en tant que balise de grain court. Dans l'exemple précédent, juste après l'allocation en gras taguée ad, nous avons une allocation de 5 × 16 + 4 = 84 octets de la balise 5c.

Une balise de mémoire nulle (par exemple, tags: ad/00 (ptr/mem)) indique un bug d'utilisation de la pile après le retour.

Dump de registre

Le vidage de registre dans les rapports HWASan correspond à l'instruction qui a effectué l'accès à la mémoire incorrect. Ce vidage est suivi d'un autre vidage de registre du gestionnaire de signaux Android standard. Ignorez le deuxième vidage, car il a été effectué lorsque HWASan a appelé abort() et n'est pas pertinent pour le bug.

Symbolisation

Pour obtenir les noms des fonctions et les numéros de ligne dans les traces de pile (et obtenir les noms de variables pour les bugs d'utilisation après le champ d'application), une étape de symbolisation hors connexion est nécessaire.

Première configuration: installez llvm-symbolizer

Pour symboliser, llvm-symbolizer doit être installé et accessible depuis $PATH sur votre système. Sur Debian, vous pouvez l'installer à l'aide de sudo apt install llvm.

Obtenir des fichiers de symboles

Pour la symbolisation, nous avons besoin de binaires non tronqués contenant des symboles. Leur emplacement dépend du type de compilation:

  • Pour les compilations locales, les fichiers de symboles se trouvent dans out/target/product/<product>/symbols/.
  • Pour les builds AOSP (par exemple, flashés à partir d'Android Flash Tool), les builds sont sur Android CI. Dans les artefacts de la compilation, il existe un fichier ${PRODUCT}-symbols-${BUILDID}.zip.
  • Pour les compilations internes de votre organisation, consultez la documentation de votre organisation pour obtenir de l'aide pour obtenir des fichiers de symboles.

Symboliser

hwasan_symbolize --symbols <DECOMPRESSED_DIR>/out/target/product/*/symbols < crash

Comprendre les rapports sur la pile

Pour les bugs qui se produisent avec des variables de pile, le rapport HWASan contient des informations telles que les suivantes:

Cause: stack tag-mismatch
Address 0x007d4d251e80 is located in stack of thread T64
Thread: T64 0x0074000b2000 stack: [0x007d4d14c000,0x007d4d255cb0) sz: 1088688 tls: [0x007d4d255fc0,0x007d4d259000)
Previously allocated frames:
  record_addr:0x7df7300c98 record:0x51ef007df3f70fb0  (/apex/com.android.art/lib64/libart.so+0x570fb0)
  record_addr:0x7df7300c90 record:0x5200007df3cdab74  (/apex/com.android.art/lib64/libart.so+0x2dab74)
  [...]

Pour vous aider à comprendre les bugs de pile, HWASan suit les frames de pile précédents. HWASan ne les transforme pas en contenu compréhensible par l'humain dans le rapport de bug et nécessite une étape de symbolisation supplémentaire.

Non-respect de la procédure de résolution des litiges en ligne

Certains bugs d'utilisation après libération signalés par HWASan peuvent indiquer une violation de la règle de définition unique (ODR). Une violation de l'ODR se produit lorsqu'une même variable est définie plusieurs fois dans le même programme. Cela signifie également que la variable est détruite plusieurs fois, ce qui peut entraîner une erreur d'utilisation après libération.

Après la symbolisation, les cas de non-respect de l'ODR affichent une erreur d'utilisation après libération avec __cxa_finalize, à la fois sur la pile d'accès non valide et sur la pile libérée ici. La pile allouée ici précédemment contient __dl__ZN6soinfo17call_constructorsEv et doit pointer vers l'emplacement de votre programme qui définit la variable plus haut dans la pile.

L'ODR peut être enfreint si des bibliothèques statiques sont utilisées. Si une bibliothèque statique qui définit un global C++ est liée à plusieurs bibliothèques partagées ou exécutables, plusieurs définitions du même symbole peuvent exister dans le même espace d'adresses, ce qui entraîne une erreur ODR.

Dépannage

Cette section décrit certaines erreurs et explique comment les résoudre.

HWAddressSanitizer ne peut pas décrire l'adresse plus en détail

Il arrive parfois que HWASan manque d'espace pour les informations sur les allocations de mémoire précédentes. Dans ce cas, le rapport ne contient qu'une seule trace de pile pour l'accès à la mémoire immédiat, suivie d'une note:

HWAddressSanitizer can not describe address in more detail.

Dans certains cas, vous pouvez résoudre ce problème en exécutant le test plusieurs fois. Une autre option consiste à augmenter la taille de l'historique HWASan. Vous pouvez le faire globalement dans build/soong/cc/sanitize.go (recherchez hwasanGlobalOptions) ou dans votre environnement de processus (essayez adb shell echo $HWASAN_OPTIONS pour afficher les paramètres actuels).

Cette erreur peut également se produire si la mémoire accessible n'est pas mappée ou allouée par un alloueur non compatible avec HWASan. Dans ce cas, la balise mem indiquée dans l'en-tête de plantage est généralement 00. Si vous avez accès à la pierre tombale complète, il peut être utile de consulter le vidage des cartes de mémoire pour déterminer à quel mappage (le cas échéant) l'adresse appartient.

Bug imbriqué dans le même thread

Cela signifie qu'un bug s'est produit lors de la génération du rapport d'erreur HWASan. Cela est généralement dû à un bug dans l'environnement d'exécution HWASan. Envoyez un bug et fournissez des instructions pour reproduire le problème, si possible.