Debug e mitigazione degli errori di memoria

Android supporta diversi strumenti per il debug degli errori di memoria. Ognuno presenta vantaggi e svantaggi, pertanto leggi quanto segue per decidere qual è il più adatto al tuo caso d'uso. Questo documento offre una panoramica degli strumenti disponibili per consentirti di decidere quali approfondire, ma in breve l'obiettivo è riassumere i documenti specifici per tali strumenti.

tl;dr

  • Utilizza un linguaggio sicuro per la memoria, ove possibile, per evitare errori di memoria
  • Utilizza sempre il metodo 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 i test
  • I dispositivi che supportano MTE non sono disponibili a livello generale nel 2023, ma utilizzali se riesci a rilevare errori in produzione
  • Utilizza ASan durante il test solo come ultima risorsa

Lingue con memoria sicura

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

I linguaggi ufficialmente sicuri per Android sono Java e Kotlin. Lo sviluppo della maggior parte delle applicazioni Android è più facile in una di queste lingue.

Detto questo, esistono sviluppatori che scrivono codice di spedizione in Rust e, se stai leggendo questa pagina, probabilmente hai un buon motivo per utilizzare il codice nativo (portabilità, prestazioni o entrambi). Rust è la scelta migliore per il codice nativo con memoria sicura su Android. Il team di NDK non è necessariamente in grado di aiutarti con i problemi che hai riscontrato se scegli questa strada, ma ci interessa ascoltarli.

PAC/BTI

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

Queste funzionalità sono compatibili con i dispositivi che non le supportano in quanto le nuove istruzioni utilizzate non sono operazioni possibili sui dispositivi precedenti. È anche necessario disporre di un kernel sufficiente e di una nuova versione del sistema operativo. La ricerca di paca e bti in /proc/cpuinfo mostra se disponi di nuovo hardware sufficiente e di un kernel sufficiente. Android 12 (API 31) dispone del supporto necessario per lo spazio utente.

Vantaggi:

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

Contro:

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

Google Workspace for Education

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

Vantaggi:

  • Nessun overhead CPU o memoria significativo
  • Prova del deployment: non richiede la ricreazione di codice nativo
  • Funziona per le app a 32 bit

Contro:

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

HWASan

Il sanificatore per indirizzi hardware, noto anche come HWASan, è la soluzione migliore per individuare gli errori di memoria durante i test. È utile se utilizzato insieme ai test automatici, specialmente se stai eseguendo test fuzz, ma a seconda delle esigenze di prestazioni della tua app, potrebbe essere utilizzabile anche sui telefoni di fascia alta in un'impostazione sperimentale.

Vantaggi:

  • Nessun falso positivo
  • Rileva ulteriori classi di errori che ASan non può (utilizzare l'impilamento dopo il reso)
  • Tasso più basso di falsi negativi rispetto a MTE (1 su 256 contro 1 su 16)
  • Riduzione dell'overhead di memoria rispetto ad ASan, l'alternativa più vicina

Contro:

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

MTE

L'estensione di tagging della memoria, nota anche come MTE, è un'alternativa a costi inferiori rispetto a HWASan, destinata all'uso sul campo. Se disponi di hardware per testare le build MTE, devi abilitarlo.

Vantaggi:

  • Sovraccarico sufficientemente basso per essere tollerabile in produzione per molte app
  • Nessun falso positivo
  • Non richiede la ricostruzione del codice per rilevare gli errori di heap (ma rileva gli errori di stack)

Contro:

  • Non sono disponibili dispositivi disponibili in commercio con MTE abilitata nel 2023
  • Tasso falso negativo di 1 su 16 rispetto a 1 su 256 di HWASan
  • Disponibile solo per le app a 64 bit
  • Richiede la creazione di librerie separate per il targeting di dispositivi abilitati per MTE e non abilitati per MTE

San

Il disinfettante per indirizzi, noto anche come ASan, è il più vecchio e il più disponibile tra gli strumenti disponibili. È utile per rilevare errori di memoria durante i test e il debug dei problemi che interessano solo i vecchi dispositivi in cui non sono disponibili nessuno degli altri strumenti. Quando possibile, scegli HWASan.

Vantaggi:

  • Ampia disponibilità. Potrebbe funzionare su dispositivi precedenti a KitKat
  • Nessun falso positivo o negativo quando utilizzato correttamente

Contro:

  • Difficile da costruire e imballare correttamente
  • Overhead più elevato di tutte le opzioni: ~100% di CPU, ~50% di codice, ~100% di memoria utilizzata
  • Non più supportata
  • Presenta bug noti che non saranno risolvibili