AddressSanitizer con l'aiuto dell'hardware

Consulta Informazioni sui report HWASan per informazioni su come leggere gli arresti anomali di HWASan.

Hardware-assisted AddressSanitizer (HWASan) è uno strumento di rilevamento degli errori di memoria simile ad AddressSanitizer. HWASan utilizza molta meno RAM rispetto ad ASan, il che lo rende adatto alla sanificazione dell'intero sistema. HWASan è disponibile solo su Android 10 e versioni successive e solo su hardware AArch64.

Sebbene sia utile principalmente per il codice C/C++, HWASan può anche aiutare a eseguire il debug del codice Java che causa arresti anomali in C/C++ utilizzato per implementare interfacce Java. È utile perché rileva gli errori di memoria quando si verificano, indicando direttamente il codice responsabile.

Rispetto ad ASan classico, HWASan presenta:

  • Overhead della CPU simile (~2x)
  • Overhead delle dimensioni del codice simile (40-50%)
  • Overhead della RAM molto inferiore (10-35%)

HWASan rileva lo stesso insieme di bug di ASan:

  • Overflow/underflow del buffer dello stack e dell'heap
  • Heap use-after-free
  • Utilizzo dello stack al di fuori dell'ambito
  • Double free/wild free

Inoltre, HWASan rileva l'utilizzo dello stack dopo il ritorno.

HWASan (come ASan) è compatibile con UBSan, entrambi possono essere attivati contemporaneamente su una destinazione.

Dettagli di implementazione e limitazioni

HWASan si basa sull'approccio di assegnazione di tag alla memoria, in cui un piccolo valore di tag casuale viene associato sia ai puntatori sia agli intervalli di indirizzi di memoria. Affinché l'accesso a una memoria sia valido, i tag puntatore e memoria devono corrispondere. HWASan si basa sulla funzionalità ARMv8 di ignorare il byte più significativo (TBI), chiamata anche assegnazione di tag agli indirizzi virtuali, per memorizzare il tag del puntatore nei bit più significativi dell'indirizzo.

Puoi scoprire di più sulla progettazione di HWASan sul sito della documentazione di Clang.

Per progettazione, HWASan non dispone delle zone rosse di dimensioni limitate di ASan per rilevare overflow o della quarantena di capacità limitata di ASan per rilevare l'uso dopo la liberazione. Per questo motivo, HWASan può rilevare un bug indipendentemente dalle dimensioni dell'overflow o da quanto tempo fa è stata deallocata la memoria. Ciò offre a HWASan un grande vantaggio rispetto ad ASan.

Tuttavia, HWASan ha un numero limitato di valori di tag possibili (256), il che significa che esiste una probabilità dello 0,4% di non rilevare alcun bug durante un'esecuzione del programma.

Requisiti

Le versioni recenti (4.14+) del kernel Android comune supportano HWASan preconfigurato. I rami specifici di Android 10 non supportano HWASan.

Il supporto dello spazio utente per HWASan è disponibile a partire da Android 11.

Se utilizzi un kernel diverso, HWASan richiede che il kernel Linux accetti puntatori taggati negli argomenti delle chiamate di sistema. Il supporto è stato implementato nei seguenti patchset upstream:

Se esegui la compilazione con una toolchain personalizzata, assicurati che includa tutto fino al commit LLVM c336557f.

Utilizzare HWASan

Utilizza i seguenti comandi per creare l'intera piattaforma utilizzando HWASan:

lunch aosp_walleye-userdebug # (or any other product)
export SANITIZE_TARGET=hwaddress
m -j

Per comodità, puoi aggiungere l'impostazione SANITIZE_TARGET a una definizione di prodotto, in modo simile a aosp_coral_hwasan.

Per gli utenti che hanno familiarità con AddressSanitizer, gran parte della complessità della build è scomparsa:

  • Non è necessario eseguire make due volte.
  • Le build incrementali funzionano subito.
  • Non è necessario eseguire il flashing di userdata.

Sono state rimosse anche alcune limitazioni di AddressSanitizer:

  • Sono supportati gli eseguibili statici.
  • È possibile saltare la sanificazione di qualsiasi target diverso da libc. A differenza di ASan, non è obbligatorio che se una libreria viene sanificata, lo sia anche qualsiasi eseguibile che la collega.

Il passaggio tra HWASan e le immagini regolari con lo stesso numero di build (o un numero superiore) può essere essere eseguito liberamente. Non è necessario cancellare i dati del dispositivo.

Per ignorare la sanificazione di un modulo, utilizza LOCAL_NOSANITIZE := hwaddress (Android.mk) o sanitize: { hwaddress: false } (Android.bp).

Sanitizzare singoli target

HWASan può essere abilitato per target in una build normale (non sanificata), a condizione che anche libc.so sia sanificato. Aggiungi hwaddress: true al blocco sanitize in "libc_defaults" in bionic/libc/Android.bp. Poi fai lo stesso nel target su cui stai lavorando.

Tieni presente che la sanificazione di libc consente il tagging delle allocazioni di memoria heap a livello di sistema, nonché il controllo dei tag per le operazioni di memoria all'interno di libc.so. In questo modo è possibile rilevare bug anche nei file binari su cui HWASan non è stato attivato se l'accesso alla memoria errato si trova in libc.so (ad es. pthread_mutex_unlock() su un mutex delete().

Non è necessario modificare alcun file di build se l'intera piattaforma è creata utilizzando HWASan.

Analisi dello stack migliori

HWASan utilizza un unwinder rapido basato su frame pointer per registrare una traccia dello stack per ogni evento di allocazione e deallocazione della memoria nel programma. Android attiva i puntatori di frame nel codice AArch64 per impostazione predefinita, quindi funziona alla perfezione. Se devi eseguire il unwind tramite codice gestito, imposta HWASAN_OPTIONS=fast_unwind_on_malloc=0 nell'ambiente del processo. Tieni presente che le tracce dello stack di accesso alla memoria errato utilizzano per impostazione predefinita l'unwinder "lento"; questa impostazione influisce solo sulle tracce di allocazione e deallocazione. Questa opzione può richiedere molta CPU, a seconda del carico.

Simbolizzazione

Consulta Simbolizzazione in "Comprendere i report HWASan".

HWASan nelle app

Analogamente ad AddressSanitizer, HWASan non può vedere il codice Java, ma può rilevare bug nelle librerie JNI. Fino ad Android 14, l'esecuzione di app HWASan su un dispositivo non HWASan non era supportata.

Su un dispositivo HWASan, le app possono essere controllate con HWASan compilando il codice con SANITIZE_TARGET:=hwaddress in Make o -fsanitize=hwaddress nei flag del compilatore. Su un dispositivo non HWASan (con Android 14 o versioni successive), deve essere aggiunta un'impostazione del file wrap.sh LD_HWASAN=1. Per ulteriori dettagli, consulta la documentazione per gli sviluppatori di app.