Puntatori contrassegnati

A partire da Android 11, per i processi a 64 bit, tutte le allocazioni heap hanno un tag definito dall'implementazione impostato nel byte principale del puntatore sui dispositivi con supporto del kernel per ARM Top-byte Ignore (TBI). Qualsiasi applicazione che modifica questo tag viene terminata quando il tag viene controllato durante la deallocazione. Ciò è necessario per l'hardware futuro con supporto ARM Memory Tagging Extension (MTE).

Byte principale Ignora

La funzione Top-byte Ignore di ARM è disponibile per il codice a 64 bit in tutto l'hardware Armv8 AArch64. Questa funzionalità significa che l'hardware ignora il byte principale di un puntatore quando accede alla memoria.

TBI richiede un kernel compatibile che gestisca correttamente i puntatori con tag passati dallo spazio utente. I kernel comuni Android dalla versione 4.14 (Pixel 4) e versioni successive presentano le patch TBI richieste.

I dispositivi con supporto TBI nel kernel vengono rilevati dinamicamente all'avvio del processo e un tag dipendente dall'implementazione viene inserito nel byte principale del puntatore per tutte le allocazioni heap. Successivamente, viene eseguito un controllo per garantire che il tag non sia stato troncato durante la deallocazione della memoria.

Disponibilità dell'estensione di tagging della memoria

Memory Tagging Extension (MTE) di ARM aiuta a risolvere i problemi di sicurezza della memoria. MTE funziona contrassegnando i bit di indirizzo dal 56° al 59° di ciascuna allocazione di memoria sullo stack, sull'heap e sui globali. L'hardware e il set di istruzioni controllano automaticamente che venga utilizzato il tag corretto ad ogni accesso alla memoria.

Le app Android che memorizzano erroneamente le informazioni nel byte superiore del puntatore si interrompono sicuramente su un dispositivo abilitato MTE . I puntatori con tag rendono più semplice rilevare e rifiutare usi errati del byte principale del puntatore prima che i dispositivi MTE siano disponibili.

Supporto per gli sviluppatori

Se la tua app si è bloccata e ti è stato richiesto questo collegamento, potrebbe significare uno dei seguenti:

  1. L'applicazione ha tentato di liberare un puntatore non allocato dall'allocatore heap del sistema.
  2. Qualcosa nella tua app ha modificato il byte principale di un puntatore. Il byte principale del puntatore non può essere modificato e il codice deve essere modificato per risolvere questo problema.

Esempi di puntatore al byte superiore utilizzato o modificato in modo errato.

  • I puntatori a un tipo particolare hanno metadati specifici dell'applicazione memorizzati nei primi 16 bit dell'indirizzo.
  • Un puntatore lanciato su double e poi indietro, perdendo i bit di indirizzo inferiori.
  • Codice che calcola la differenza tra gli indirizzi delle variabili locali di diversi stack frame come modo per misurare la profondità di ricorsione.

Alcune applicazioni potrebbero dipendere da librerie che si comportano in modo errato quando viene impostato il byte superiore del puntatore. Riconosciamo che potrebbe non essere banale risolvere rapidamente questi problemi di fondo nelle biblioteche. Pertanto, le applicazioni che utilizzano targetSdkLevel < 30 non avranno il tagging del puntatore abilitato per impostazione predefinita. Forniamo anche una via di fuga per le applicazioni create con targetSdkLevel >= 30 per facilitare il periodo di transizione.

Il portello di fuga viene utilizzato aggiungendo quanto segue al file AndroidManifest.xml :

  <application android:allowNativeHeapPointerTagging="false">
  ...
  </application>

Ciò disabiliterà la funzionalità di codifica del puntatore per la tua applicazione. Tieni presente che ciò non risolve il problema di integrità del codice sottostante. Questa via di fuga scomparirà nelle future versioni di Android, perché problemi di questo tipo saranno incompatibili con MTE .