Comprensione dei report HWASan

Quando lo strumento HWASan rileva un bug di memoria, il processo viene terminato con abort() e viene stampato un report su stderr e logcat. Come tutti gli arresti anomali nativi su Android, gli errori HWASan possono essere trovati in /data/tombstones .

Rispetto ai normali arresti anomali nativi, HWASan contiene informazioni aggiuntive nel campo "Messaggio di interruzione" vicino alla parte superiore della lapide. Di seguito è riportato un esempio di arresto anomalo basato sull'heap (per i bug dello stack, vedere la nota seguente per le sezioni specifiche dello stack).

Rapporto di esempio

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
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 …]

Questo è molto simile a un report AddressSanitizer . A differenza di questi, quasi tutti i bug HWASan sono "tag-mismatch", ovvero un accesso alla memoria in cui un tag puntatore non corrisponde al tag di memoria corrispondente. Questo potrebbe essere uno dei

  • accesso fuori limite su stack o heap
  • utilizzare dopo libero sull'heap
  • utilizzare dopo la restituzione in pila

Sezioni

Di seguito è riportata una spiegazione di ciascuna sezione del rapporto HWASan:

Errore di accesso

Contiene informazioni sull'accesso errato alla memoria, tra cui:

  • Tipo di accesso ("LETTURA" vs. "SCRITTURA")
  • Dimensioni di accesso (quanti byte sono stati tentati di accedere)
  • Numero di thread di accesso
  • Puntatore e tag di memoria (per il debug avanzato)

Accedere all'analisi dello stack

Analisi dello stack dell'accesso errato alla memoria. Vedere la sezione Simbolizzazione per simbolizzare.

Causa

La potenziale causa dell'accesso non corretto. Se sono presenti più candidati, questi vengono elencati in ordine decrescente di probabilità. Precede le informazioni dettagliate sulla potenziale causa. HWASan è in grado di diagnosticare le seguenti cause:

  • utilizzare dopo-libero
  • stack tag-mismatch: può essere stack use-after-return / use after-scope o out of bounds
  • overflow del buffer di heap
  • overflow globale

Informazioni sulla memoria

Descrive cosa sa HWASan sulla memoria a cui si accede e può variare in base al tipo di bug.

Tipo di bug Causa Formato del rapporto
mancata corrispondenza dei tag utilizzare dopo-libero
<address> is located N bytes inside of M-byte region [<start>, <end>)
  freed by thread T0 here:
overflow del buffer di heap Tieni presente che questo può anche essere un underflow.
<address> is located N bytes to the right of M-byte region [<start>, <end>)
  allocated here:
mancata corrispondenza dei tag dello stack I report sugli stack non fanno differenza tra overflow/underflow e bug use-after-return. Inoltre, per trovare l'allocazione dello stack che è all'origine dell'errore, è necessaria una fase di simbolizzazione offline. Consulta la sezione Informazioni sui report sullo stack di seguito.
esente da invalidi utilizzare dopo-libero Questo è un doppio bug gratuito. Se ciò accade all'arresto del processo, ciò può significare una violazione dell'ODR .
<address> is located N bytes inside of M-byte region [<start>, <end>)
  freed by thread T0 here:
non posso descrivere l'indirizzo O un wild free (libero di memoria che non era stata allocata prima) o un double free dopo che la memoria allocata è stata eliminata dal buffer libero di HWASan.
0x… è la memoria ombra HWAsan. Si tratta sicuramente di un'azione gratuita, poiché l'applicazione stava tentando di liberare la memoria interna di HWASan.

Traccia dello stack di deallocazione

Stack trace del punto in cui è stata deallocata la memoria. Presente solo per bug use-after-free o invalid-free. Vedere la sezione Simbolizzazione per simbolizzare.

Traccia dello stack di allocazione

Traccia dello stack della posizione in cui è stata allocata la memoria. Vedere la sezione Simbolizzazione per simbolizzare.

Informazioni di debug avanzate

Il report HWASan presenta anche alcune informazioni di debug avanzate, tra cui (in ordine):

  1. L'elenco dei thread nel processo
  2. L'elenco dei thread nel processo
  3. Il valore dei tag di memoria vicino alla memoria che ha causato l'errore
  4. Il dump dei registri nel punto di accesso alla memoria

Dump dei tag di memoria

Il tag memory dump può essere utilizzato per cercare allocazioni di memoria vicine con lo stesso tag del tag puntatore. Questi potrebbero indicare un accesso fuori limite con un ampio spostamento. Un tag corrisponde a 16 byte di memoria; il tag puntatore rappresenta i primi 8 bit dell'indirizzo. Il tag memory dump può fornire suggerimenti, ad esempio quanto segue è un overflow del buffer a destra:

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  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..  ..
(notare la sequenza di 6 × 16 = 96 byte di tag "ad" a sinistra che corrispondono al tag del puntatore).

Se la dimensione di un'allocazione non è un multiplo di 16, la parte rimanente della dimensione verrà memorizzata come tag di memoria e il tag verrà memorizzato come tag granulo corto . Nell'esempio precedente, subito dopo l'allocazione in grassetto dell'annuncio con tag, abbiamo un'allocazione di 5 × 16 + 4 = 84 byte del tag 5c.

Un tag di memoria pari a zero (es. tags: ad/ 00 (ptr/mem) ) di solito indica un bug di utilizzo dello stack dopo il ritorno.

Registrati Dump

Il dump del registro nei report HWASan corrisponde all'istruzione effettiva che ha eseguito l'accesso alla memoria non valido. È seguito da un altro dump del registro dal normale gestore del segnale Android: ignora il secondo , viene eseguito quando HWASan ha chiamato abort() e non è rilevante per il bug.

Simbolizzazione

Per ottenere nomi di funzioni e numeri di riga nelle analisi dello stack (e ottenere nomi di variabili per bug di utilizzo dopo ambito), è necessario un passaggio di simbolizzazione offline.

Prima configurazione: installa llvm-symbolizer

Per simbolizzare, il tuo sistema deve avere llvm-symbolizer installato e accessibile da $PATH. Su Debian, puoi installarlo usando sudo apt install llvm .

Ottenere file di simboli

Per la simbolizzazione, abbiamo bisogno di binari non strippati contenenti simboli. Dove è possibile trovarli dipende dal tipo di build:

Per le build locali , i file di simboli possono essere trovati in out/target/product/<product>/symbols/ .

Per le build AOSP (ad esempio flashate da Flashstation ), le build possono essere trovate su Android CI . Negli "Artefatti" della build, ci sarà un file `${PRODUCT}-symbols-${BUILDID}.zip`.

Per le build interne della tua organizzazione, controlla la documentazione della tua organizzazione per ottenere assistenza su come ottenere i file dei simboli.

Simboleggiare

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

Comprendere i report sugli stack

Per i bug che si verificano con le variabili dello stack, il rapporto HWASan conterrà dettagli come questi:

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)
  [...]
	

Per consentire la comprensione dei bug dello stack, HWASan tiene traccia degli stack frame avvenuti in passato. Attualmente, HWASan non trasforma questi contenuti in contenuti comprensibili dall'uomo nella segnalazione di bug e richiede un ulteriore passaggio di simbolizzazione .

Violazioni dell'ODR

Alcuni bug use-after-free segnalati da HWASan possono anche indicare una violazione della One Definition Rule (ODR). Una violazione ODR si verifica quando la stessa variabile viene definita più volte nello stesso programma. Ciò significa anche che la variabile viene distrutta più volte, il che potrebbe portare all'errore use-after-free.

Dopo la simbolizzazione, le violazioni ODR mostrano un use-after-free con __cxa_finalize , sia sullo stack di accesso non valido che sullo stack "liberato qui". Lo stack "precedentemente allocato qui" contiene __dl__ZN6soinfo17call_constructorsEv e dovrebbe puntare alla posizione nel programma che definisce la variabile più in alto nello stack.

Uno dei motivi per cui l'ODR potrebbe essere violato è l'utilizzo di librerie statiche. Se una libreria statica che definisce un globale C++ è collegata a più librerie o eseguibili condivisi, più definizioni dello stesso simbolo potrebbero esistere nello stesso spazio di indirizzi, causando un errore ODR.

Risoluzione dei problemi

"HWAddressSanitizer non è in grado di descrivere l'indirizzo in modo più dettagliato."

A volte HWASan può esaurire lo spazio per le informazioni sulle allocazioni di memoria passate. In tal caso il report conterrà un solo stack trace per l'accesso immediato alla memoria, seguito da una nota:

  HWAddressSanitizer can not describe address in more detail.

In alcuni casi questo può essere risolto eseguendo il test più volte. Un'altra opzione è aumentare la dimensione della cronologia HWASan. Questo può essere fatto a livello globale in build/soong/cc/sanitize.go (cerca hwasanGlobalOptions ) o nel tuo ambiente di processo (prova adb shell echo $HWASAN_OPTIONS per vedere le impostazioni correnti).

Ciò può verificarsi anche se la memoria a cui si accede non è mappata o allocata da un allocatore non compatibile con HWASan. In questo caso, il tag mem elencato nell'intestazione del crash sarà generalmente 00 . Se hai accesso alla rimozione completa, potrebbe essere utile consultare il dump delle mappe di memoria per scoprire a quale mappatura (se presente) appartiene l'indirizzo.

"bug annidato nello stesso thread"

Ciò significa che si è verificato un bug durante la generazione del rapporto sugli arresti anomali di HWASan. Ciò è solitamente dovuto a un bug nel runtime HWASan, segnala un bug e fornisci istruzioni su come riprodurre il problema, se possibile.