Debug e mitigazione degli errori di memoria

Android supporta diversi strumenti per il debug degli errori di memoria. Ciascuno ha dei compromessi, quindi continua a leggere per decidere qual è il più adatto al tuo caso d'uso. Questo documento fornisce una panoramica degli strumenti disponibili in modo che tu possa decidere quali ulteriori indagini, ma è inteso a essere conciso, quindi leggi la documentazione specifica per lo strumento per maggiori dettagli.

TL;DR

  • Quando possibile, utilizza un linguaggio sicuro per la memoria per evitare errori di memoria
  • Utilizza sempre PAC/BTI per mitigare gli attacchi ROP/JOP
  • Utilizza sempre GWP-ASan per rilevare rari errori di memoria in produzione
  • Utilizza HWASan per rilevare errori di memoria durante il test
  • I dispositivi compatibili con MTE non sono generalmente disponibili nel 2023, ma utilizzali se riesci a rilevare errori in produzione
  • Utilizzare ASan durante i test solo come ultima alternativa

Lingue che supportano la memoria

Un linguaggio sicuro per la memoria è l'unico modo per evitare e mitigare completamente gli errori della memoria. Gli altri strumenti in questa pagina possono aiutarti a rendere la memoria non sicura più sicura e affidabile, ma l'utilizzo di un linguaggio sicuro per la memoria elimina l'intera classe di problemi.

I linguaggi sicuri per la memoria supportati ufficialmente per Android sono Java e Kotlin. La maggior parte delle app Android è più facile da sviluppare in una di queste lingue.

Detto questo, ci sono sviluppatori di app che pubblicano codice scritto in Rust e, se stai leggendo questa pagina, probabilmente hai un buon motivo per aver bisogno di codice nativo (portabilità, prestazioni o entrambi). Rust è la scelta migliore per il codice nativo della memoria su Android. Il team di NDK non è necessariamente in grado di aiutarti a risolvere i problemi riscontrati se scegli questa strada, ma siamo interessati a sentirne alcuni.

PAC/ITC

Pointer Authentication e Branch Target Identification, anche noti come PAC/BTI, sono strumenti di mitigazione adatti all'uso in produzione. Sebbene siano tecnologie separate, sono controllate dallo stesso flag del compilatore, quindi sono sempre utilizzate insieme.

Queste funzionalità sono compatibili con le versioni precedenti dei dispositivi che non le supportano, in quanto le nuove istruzioni utilizzate sono inutilizzabili sui dispositivi precedenti. È inoltre necessario avere un kernel e una versione del sistema operativo sufficienti. La ricerca di paca e bti in /proc/cpuinfo indica se disponi di hardware e kernel abbastanza nuovo. Android 12 (API 31) dispone del supporto necessario per lo spazio utente.

Pro:

  • Può essere abilitato in tutte le build senza causare problemi su dispositivi o kernel meno recenti (ma assicurati di aver effettivamente testato su una combinazione dispositivo/kernel/sistema operativo che lo supporta)

Contro:

  • Disponibile solo per app a 64 bit
  • Non riduce gli errori sui dispositivi che non la supportano
  • Overhead per dimensioni del codice dell'1%

GWP-Asan

GWP-ASan può essere utilizzato per rilevare errori di memoria nel campo, ma la frequenza di campionamento è troppo bassa per essere una mitigazione efficace.

Pro:

  • Nessun overhead significativo di CPU o memoria
  • Difficoltà di deployment: non è necessario ricreare il codice nativo
  • Compatibile con le app a 32 bit

Contro:

  • Una frequenza di campionamento bassa richiede un elevato numero di utenti per individuare i bug in modo efficace
  • Rileva solo gli errori di heap, non gli errori dello stack

HWASan

Il sanitizer per indirizzi hardware, noto anche come HWASan, è la soluzione migliore per rilevare gli errori di memoria durante i test. È più utile quando viene utilizzato con test automatici, soprattutto se esegui test fuzz, ma, a seconda delle esigenze di prestazioni della tua app, potrebbe essere utilizzabile anche su telefoni di fascia alta in versione sperimentale.

Pro:

  • Nessun falsi positivi
  • Rileva classi aggiuntive di errori che ASan non può (utilizzo in stack dopo il reso)
  • Tasso di falsi negativi inferiore rispetto a MTE (1 su 256 contro 1 su 16)
  • Un overhead di memoria minore rispetto ad ASan, l'alternativa più vicina

Contro:

  • Notevole overhead per la CPU (~100%), la dimensione del codice (~50%) e la memoria (10% -35%)
  • Fino a API 34 e NDK r26, è necessario eseguire il flashing di un'immagine compatibile con HWASan
  • Funziona solo su app a 64 bit

MTE

L'estensione per il tagging della memoria, nota anche come MTE, è un'alternativa più economica a HWASan. Oltre alle funzionalità di debug e test, può essere utilizzata per rilevare e ridurre il danneggiamento della memoria in produzione. Se hai l'hardware per testare le build MTE, devi abilitarlo.

Pro:

  • Overhead sufficientemente basso da essere tollerabile in produzione per molte app
  • Nessun falsi positivi
  • Non richiede la ricreazione del codice per rilevare errori di heap (ma per rilevare gli errori dello stack)

Contro:

  • Non ci sono dispositivi disponibili in commercio con MTE abilitato per impostazione predefinita nel 2024, ma la documentazione di Arm spiega come abilitare MTE per i test su Pixel 8/Pixel 8 Pro.
  • Tasso di falsi negativi di 1 su 16 rispetto a 1 su 256 di HWASan
  • Disponibile solo per app a 64 bit
  • Richiede la creazione di librerie separate per il targeting di dispositivi abilitati e non MTE

ASan

La soluzione di sanitizzazione degli indirizzi, nota anche come ASan, è lo strumento meno recente e più ampiamente disponibile. È utile per rilevare gli errori di memoria durante i test e il debug di problemi che interessano solo i dispositivi meno recenti dove nessuno degli altri strumenti è disponibile. Se possibile, preferisci HWASan.

Pro:

  • Ampia disponibilità. Potrebbe funzionare su dispositivi precedenti a Lollipop
  • Nessun falsi positivi o negativo se utilizzato correttamente

Contro:

  • È difficile creare e pacchettizzare correttamente
  • Overhead massimo tra tutte le opzioni: ~100% CPU, ~50% dimensione codice, ~100% memoria utilizzata
  • Non più supportato
  • Ha bug noti che non verranno risolti