Android supporta diversi strumenti per il debug degli errori di memoria. Ognuna presenta dei compromessi, quindi leggi di seguito per decidere quale è la migliore per il tuo caso d'uso. Questo documento fornisce una panoramica degli strumenti disponibili per aiutarti a decidere quali approfondire, ma è conciso, quindi leggi i documenti specifici dello strumento per i dettagli.
tl;dr
- Utilizza un linguaggio memory-safe quando possibile per rendere impossibili gli errori di memoria
- Utilizza sempre PAC/BTI per mitigare gli attacchi ROP/JOP
- Utilizza sempre GWP-ASan per rilevare errori di memoria rari in produzione
- Utilizzare HWASan per rilevare errori di memoria durante i test
- MTE è disponibile come opzione su dispositivi selezionati.
- Utilizza ASan durante i test solo come ultima risorsa
Linguaggi memory-safe
Un linguaggio memory-safe è l'unico modo per evitare e mitigare completamente gli errori di memoria. Gli altri strumenti in questa pagina possono aiutarti a rendere il codice non sicuro per la memoria più sicuro e affidabile, ma l'utilizzo di un linguaggio sicuro per la memoria elimina l'intera classe di problemi.
I linguaggi con sicurezza della memoria supportati ufficialmente per Android sono Java e Kotlin. La maggior parte delle applicazioni per Android è più facile da sviluppare in una di queste lingue.
Detto questo, ci sono sviluppatori di app che distribuiscono 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 sicuro per la memoria su Android. Il team NDK non è necessariamente in grado di aiutarti con i problemi che riscontri se scegli questa strada, ma ci interessa conoscerli.
PAC/BTI
Pointer Authentication and Branch Target Identification, noti anche come PAC/BTI, sono strumenti di mitigazione adatti all'uso in produzione. Sebbene si tratti di tecnologie separate, sono controllate dallo stesso flag del compilatore, quindi vengono sempre utilizzate insieme.
Queste funzionalità sono compatibili con le versioni precedenti dei dispositivi che non le supportano
perché le nuove istruzioni utilizzate non hanno effetto sui dispositivi precedenti. È inoltre
necessario disporre di un kernel e di una versione del sistema operativo sufficientemente recenti.
La ricerca di paca
e bti
in /proc/cpuinfo
mostra se hai un hardware e un kernel
abbastanza nuovi. Android 12 (API 31) offre il supporto
userspace necessario.
Pro:
- Può essere attivato in tutte le build senza causare problemi su dispositivi o kernel meno recenti (ma assicurati di aver eseguito il test su una combinazione di dispositivo/kernel/sistema operativo che lo supporta).
Contro:
- Disponibile solo per app a 64 bit
- Non mitiga gli errori sui dispositivi che non lo supportano
- 1% di overhead delle dimensioni del codice
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
- Facile da implementare: non richiede la ricompilazione del codice nativo
- Funziona per le app a 32 bit
Contro:
- Una bassa frequenza di campionamento richiede un numero elevato di utenti per trovare i bug in modo efficace
- Rileva solo gli errori dell'heap, non dello stack
HWASan
Hardware Address Sanitizer, noto anche come HWASan, è lo strumento più adatto per rilevare gli errori di memoria durante i test. È più utile se utilizzato con i test automatizzati, soprattutto se esegui test fuzzing, ma a seconda delle esigenze di prestazioni della tua app, potrebbe essere utilizzabile anche su smartphone di fascia alta in un'impostazione dogfood.
Pro:
- Nessun falso positivo
- Rileva classi aggiuntive di errori che ASan non può rilevare (uso dello stack dopo il ritorno)
- Tasso di falsi negativi inferiore rispetto a MTE (1 su 256 rispetto a 1 su 16)
- Overhead di memoria inferiore rispetto ad ASan, la sua alternativa più vicina
Contro:
- Overhead significativo di CPU (~100%), dimensioni del codice (~50%) e memoria (10-35%)
- Fino all'API 34 e all'NDK r26, richiede 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 a HWASan a costi inferiori. Oltre alle funzionalità di debug e test, può essere utilizzato per rilevare e mitigare il danneggiamento della memoria in produzione. Se hai l'hardware per testare le build MTE, devi attivarle.
Pro:
- Overhead sufficientemente basso da essere tollerabile in produzione per molte app
- Nessun falso positivo
- Non richiede la ricompilazione del codice per rilevare gli errori dell'heap (ma sì per rilevare gli errori dello stack)
Contro:
- Nel 2024 non sono disponibili dispositivi in commercio con MTE abilitato per impostazione predefinita, 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 con e senza MTE
ASan
AddressSanitizer, noto anche come ASan, è il più vecchio e il più ampiamente disponibile degli strumenti disponibili. È utile per rilevare errori di memoria durante i test e per eseguire il debug di problemi che interessano solo i dispositivi meno recenti in cui non sono disponibili altri strumenti. Se possibile, preferisci HWASan.
Pro:
- Ampiamente disponibile. Potrebbe funzionare su dispositivi con KitKat
- Nessun falso positivo o negativo se utilizzato correttamente
Contro:
- Difficoltà di creazione e confezionamento corretti
- Il sovraccarico più elevato di tutte le opzioni: circa il 100% di CPU, circa il 50% di dimensioni del codice, circa il 100% di utilizzo della memoria
- Non più supportato
- Contiene bug noti che non verranno corretti