Estensione tagging memoria ARM

ARM v9 introduce la memoria ARM Tagging Extension (MTE), un'implementazione hardware di ricordo con tag.

A livello generale, MTE contrassegna ogni allocazione di memoria/deallocation con metadati aggiuntivi. Assegna un tag a una posizione di memoria, che può essere associate a puntatori che fanno riferimento a quella posizione di memoria. In fase di runtime, la CPU verifica che il puntatore e i tag dei metadati corrispondano in ogni caricamento e archiviazione.

In Android 12, l'allocatore della memoria heap del kernel e dello spazio utente ciascuna allocazione con i metadati. Questo aiuta a rilevare l'uso dopo le pulizie bug di overflow del buffer, che sono la fonte più comune di bug di sicurezza della memoria i nostri codebase.

Modalità operative degli MTE

MTE ha tre modalità operative:

  • Modalità sincrona (SYNC)
  • Modalità asincrona (ASYNC)
  • Modalità asimmetrica (ASYMM)

Modalità sincrona (SYNC)

Questa modalità è ottimizzata per la correttezza del rilevamento di bug rispetto alle prestazioni e può essere utilizzato come strumento preciso per il rilevamento di bug, quando un overhead delle prestazioni maggiore è accettabile. Se questa opzione è abilitata, MTE SYNC agisce come mitigazione della sicurezza. In caso di mancata corrispondenza dei tag, il processore interrompe l'esecuzione immediatamente e termina il processo con SIGSEGV (codice SEGV_MTESERR) e informazioni complete sull'accesso alla memoria e l'indirizzo errato.

Ti consigliamo di utilizzare questa modalità durante i test come alternativa a HWASan/KASAN o in produzione, quando il processo target rappresenta un superficie di attacco. Inoltre, quando la modalità ASYNC ha indicato la presenza di un è possibile ottenere una segnalazione di bug accurata utilizzando le API runtime per in modalità SYNC.

In modalità di sincronizzazione, l'allocatore di Android registra le analisi dello stack per tutti allocazioni e deallocations e li utilizza per fornire report sugli errori migliori che includano una spiegazione di un come use-after-free o buffer-overflow, nonché le analisi dello stack eventi di memoria pertinenti. Questi report forniscono informazioni più contestuali e facilitano l'individuazione e la correzione dei bug.

Modalità asincrona (ASYNC)

Questa modalità è ottimizzata per le prestazioni piuttosto che per l'accuratezza delle segnalazioni di bug e può da usare come rilevamento dell'overhead ridotto per i bug di sicurezza della memoria.
In caso di mancata corrispondenza dei tag, il processore continua l'esecuzione fino al più vicino una voce del kernel (ad esempio, una chiamata di sistema o un interruzione di timer), dove termina la procedura con SIGSEGV (codice SEGV_MTEAERR) senza registrando l'indirizzo o l'accesso alla memoria in errore.
Consigliamo di utilizzare questa modalità in produzione su codebase ben testati in cui la densità dei bug di sicurezza della memoria è nota per essere bassa, ottenuta utilizzando la modalità SYNC durante il test.

Modalità asimmetrica (ASYMM)

Un'ulteriore funzionalità di Arm v8.7-A, la modalità MTE asimmetrica offre il controllo delle letture della memoria e il controllo asincrono delle scritture della memoria, con prestazioni simili a quelle della modalità ASYNC. Nella maggior parte delle situazioni, è un miglioramento rispetto alla modalità ASYNC e ti consigliamo di utilizzarla anziché ASYNC ogni volta che è disponibile.

Per questo motivo, nessuna delle API descritte di seguito fa riferimento al modello . È invece possibile configurare il sistema operativo per utilizzare sempre la modalità asimmetrica quando È richiesta l'asincrona. Fai riferimento alla sezione livello MTE preferito" per ulteriori informazioni.

MTE nello spazio utente

Le seguenti sezioni descrivono come abilitare l'MTE per i processi di sistema e le app. La funzionalità MTE è disattivata per impostazione predefinita, a meno che una delle seguenti opzioni non sia per un determinato processo (vedi di seguito quali componenti sono abilitati per gli MTE).

Abilita MTE utilizzando il sistema di compilazione

Essendo una proprietà a livello di processo, l'MTE è controllato dall'impostazione del tempo di build l'eseguibile principale. Le seguenti opzioni consentono di modificare questa impostazione per singoli eseguibili o per intere sottodirectory nell'albero di origine. La viene ignorata per le librerie o qualsiasi destinazione che non sia né eseguibile né test.

1. Attivazione della funzionalità MTE in Android.bp (esempio), per un particolare progetto:

Modalità MTE Impostazione
MTE asincrono
  sanitize: {
  memtag_heap: true,
  }
MTE sincrono
  sanitize: {
  memtag_heap: true,
  diag: {
  memtag_heap: true,
  },
  }

o tra Android.mk:

Modalità MTE Impostazione
Asynchronous MTE LOCAL_SANITIZE := memtag_heap
Synchronous MTE LOCAL_SANITIZE := memtag_heap
LOCAL_SANITIZE_DIAG := memtag_heap

2. Attivazione di MTE in una sottodirectory dell'albero di origine utilizzando un prodotto variabile:

Modalità MTE Includi elenco Escludi elenco
asincrono PRODUCT_MEMTAG_HEAP_ASYNC_INCLUDE_PATHS MEMTAG_HEAP_ASYNC_INCLUDE_PATHS PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS MEMTAG_HEAP_EXCLUDE_PATHS
sincronizzazione PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS MEMTAG_HEAP_SYNC_INCLUDE_PATHS

oppure

Modalità MTE Impostazione
MTE asincrono MEMTAG_HEAP_ASYNC_INCLUDE_PATHS
MTE sincrono MEMTAG_HEAP_SYNC_INCLUDE_PATHS

oppure specificando il percorso di esclusione di un eseguibile:

Modalità MTE Impostazione
MTE asincrono PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS MEMTAG_HEAP_EXCLUDE_PATHS
MTE sincrono

Esempio (utilizzo simile a PRODUCT_CFI_INCLUDE_PATHS)

  PRODUCT_MEMTAG_HEAP_SYNC_INCLUDE_PATHS=vendor/$(vendor)
  PRODUCT_MEMTAG_HEAP_EXCLUDE_PATHS=vendor/$(vendor)/projectA \
                                    vendor/$(vendor)/projectB

Abilita MTE utilizzando le proprietà di sistema

Le impostazioni di build precedenti possono essere sostituite in fase di runtime impostando il valore seguente proprietà di sistema:

arm64.memtag.process.<basename> = (off|sync|async)

Dove basename indica il nome di base dell'eseguibile.

Ad esempio, per impostare /system/bin/ping o /data/local/tmp/ping per utilizzare l'MTE asincrono, utilizza adb shell setprop arm64.memtag.process.ping async.

Abilita MTE utilizzando una variabile di ambiente

Un altro modo per eseguire l'override dell'impostazione di build è definire l'ambiente variabile: MEMTAG_OPTIONS=(off|sync|async) Se sono definite sia la variabile di ambiente sia la proprietà di sistema, ha la precedenza.

Abilita MTE per le app

Se non specificato, l'MTE è disattivato per impostazione predefinita, ma Le app che vogliono utilizzare MTE possono farlo impostando android:memtagMode nel <application> o Tag <process> nel AndroidManifest.xml.

di Gemini Advanced. android:memtagMode=(off|default|sync|async)

Se impostato sul tag <application>, il valore influisce su tutti i processi utilizzati dall'app e può essere sostituito per i singoli processi impostando Tag <process>.

Per la sperimentazione, la compatibilità modifiche è possibile utilizzare per impostare il valore predefinito Attributo memtagMode per un'app che non specificare alcun valore nel file manifest (oppure specifica default).
Sono disponibili in System > Advanced > Developer options > App Compatibility Changes nel menu delle impostazioni globali. Impostazione NATIVE_MEMTAG_ASYNC o NATIVE_MEMTAG_SYNC attiva la funzionalità MTE per una determinata app.
In alternativa, può essere impostato utilizzando am come segue:

$ adb shell am compat enable NATIVE_MEMTAG_[A]SYNC my.app.name

Crea un'immagine di sistema MTE

Consigliamo vivamente di abilitare MTE su tutti i programmi binari nativi durante lo sviluppo e tira fuori. Ciò consente di rilevare tempestivamente i bug di sicurezza della memoria e copertura utenti, se abilitata nelle build di test.

Consigliamo vivamente di attivare MTE in modalità sincrona su tutti i programmi binari nativi durante lo sviluppo.

SANITIZE_TARGET=memtag_heap SANITIZE_TARGET_DIAG=memtag_heap m

Come per qualsiasi variabile nel sistema di compilazione, SANITIZE_TARGET può essere utilizzata come variabile di ambiente o come impostazione make (ad esempio, un product.mk file).
Tieni presente che questa operazione abilita la funzionalità MTE per tutti i processi nativi, ma non per (di cui è stato creato un fork da zygote64) per le quali è possibile eseguire MTE attivate seguendo le istruzioni sopra.

Configura il livello MTE preferito specifico per la CPU

Su alcune CPU, le prestazioni di MTE in modalità ASYMM o anche SYNC possono essere simili quella di ASYNC. Ciò rende utile l'attivazione controlli più rigidi su queste CPU quando viene richiesta una modalità di controllo meno rigorosa, per ottenere i vantaggi del rilevamento degli errori dei controlli più rigidi senza gli svantaggi in termini di prestazioni.
Per impostazione predefinita, i processi configurati per l'esecuzione in modalità ASYNC verranno eseguiti in modalità ASYNC su tutte le CPU. Per configurare il kernel in modo che esegua questi processi in modalità SYNC CPU specifiche, la sincronizzazione dei valori deve essere scritta sysfs voce /sys/devices/system/cpu/cpu<N>/mte_tcf_preferred all'avvio nel tempo. Questa operazione può essere eseguita con uno script di inizializzazione. Ad esempio, per configurare le CPU 0-1 per eseguire processi in modalità ASYNC in modalità SYNC e le CPU 2-3 devono utilizzare l'esecuzione in modalità ASYMM, Alla clausola di inizializzazione dello script di un fornitore potrebbe essere aggiunto quanto segue:

  write /sys/devices/system/cpu/cpu0/mte_tcf_preferred sync
  write /sys/devices/system/cpu/cpu1/mte_tcf_preferred sync
  write /sys/devices/system/cpu/cpu2/mte_tcf_preferred asymm
  write /sys/devices/system/cpu/cpu3/mte_tcf_preferred asymm

I tombstone dei processi in modalità ASYNC in esecuzione in modalità SYNC contengono un'etichetta un'analisi precisa dello stack della posizione dell'errore di memoria. Tuttavia, non un'analisi dello stack di allocazione o deallocation. Queste analisi dello stack vengono gestite disponibile se il processo è configurato per essere eseguito in modalità SYNC.

di Gemini Advanced. int mallopt(M_THREAD_DISABLE_MEM_INIT, level)

dove level è 0 o 1.
Disabilita l'inizializzazione della memoria in Malloc ed evita di modificare i tag di memoria a meno che non sia necessario per la correttezza.

int mallopt(M_MEMTAG_TUNING, level)

dove level è:

  • M_MEMTAG_TUNING_BUFFER_OVERFLOW
  • M_MEMTAG_TUNING_UAF

Consente di selezionare la strategia di allocazione dei tag.

  • L'impostazione predefinita è M_MEMTAG_TUNING_BUFFER_OVERFLOW.
  • M_MEMTAG_TUNING_BUFFER_OVERFLOW: consente funzionalità deterministiche Rilevamento di bug di overflow e underflow del buffer lineare assegnando tag distinti alle allocazioni adiacenti. Questa modalità ha una probabilità leggermente ridotta di rilevare bug use-after-free perché solo la metà dei possibili valori di tag disponibili per ogni posizione di memoria. Tieni presente che MTE non può rilevare l'overflow all'interno dello stesso granello di tag (chunk allineato da 16 byte) e può tralasciare overflow anche in questa modalità. Questo overflow non può essere la causa di memoria perché la memoria all'interno di un granello non viene mai utilizzata per allocazioni.
  • M_MEMTAG_TUNING_UAF: attiva i tag randomizzati in modo indipendente per una probabilità uniforme del 93% di rilevare sia l'overflow del buffer sia spaziale bug temporali (da usare dopo senza costi).

Oltre alle API descritte sopra, gli utenti esperti potrebbero voler a conoscenza di quanto segue:

  • L'impostazione del registro hardwarePSTATE.TCO può temporaneamente sopprime il controllo dei tag (esempio). Ad esempio, quando copi un intervallo di memoria con contenuti di tag sconosciuti, oppure per risolvere un collo di bottiglia delle prestazioni in un hot loop.
  • Quando utilizzi M_HEAP_TAGGING_LEVEL_SYNC, il gestore degli arresti anomali del sistema fornisce informazioni aggiuntive, come analisi dello stack di allocazione e deallocation. Questa funzionalità richiede l'accesso ai bit del tag e viene attivata passando il parametro SA_EXPOSE_TAGBITS durante l'impostazione del gestore di indicatori. Qualsiasi programma che imposti il proprio segnale gestore e delega gli arresti anomali sconosciuti al sistema uno in modo analogo.

MTE nel kernel

Per abilitare KASAN con accelerazione MTE per il kernel, configura il kernel con CONFIG_KASAN=y e CONFIG_KASAN_HW_TAGS=y. Queste configurazioni sono abilitate per impostazione predefinita sui kernel GKI, a partire da Android 12-5.10.
Questa opzione può essere controllata al momento dell'avvio utilizzando i seguenti argomenti della riga di comando:

  • kasan=[on|off] - attiva o disattiva KASAN (impostazione predefinita: on)
  • kasan.mode=[sync|async] - scegli tra la modalità sincrona e asincrona (valore predefinito: sync)
  • kasan.stacktrace=[on|off] - se raccogliere analisi dello stack (valore predefinito: on)
    • la raccolta delle analisi dello stack richiede anche stack_depot_disable=off.
  • kasan.fault=[report|panic] - se solo stampare il report, oppure esegui il panico sul kernel (predefinito: report). Indipendentemente da questo, il controllo dei tag viene disattivato dopo il primo errore segnalato.
di Gemini Advanced.

Consigliamo vivamente di utilizzare la modalità SYNC durante il richiamo, lo sviluppo test. Questa opzione deve essere abilitata a livello globale per tutti i processi utilizzando la variabile di ambiente o con il sistema di compilazione. In questa modalità, vengono rilevati i bug all'inizio del processo di sviluppo, il codebase si stabilizza più rapidamente viene evitato il costo del rilevamento dei bug in una fase successiva della produzione.

Consigliamo vivamente di utilizzare la modalità ASYNC in produzione. Ciò fornisce una bassa strumento overhead per rilevare la presenza di bug di sicurezza della memoria in un processo nonché per una maggiore difesa in profondità. Una volta rilevato un bug, lo sviluppatore può Sfruttare le API di runtime per passare alla modalità SYNC e ottenere un'analisi dello stack accurata da un insieme campione di utenti.

Ti consigliamo vivamente di configurare il livello MTE preferito specifico per la CPU per il SoC. La modalità Asymm ha in genere le stesse caratteristiche di prestazioni della modalità ASYNC, ed è quasi sempre preferibile. I core in ordine di piccole dimensioni spesso hanno un'immagine simile le prestazioni in tutte e tre le modalità e può essere configurato in modo da preferire la sincronizzazione.

Gli sviluppatori dovrebbero verificare la presenza di arresti anomali controllando la presenza di arresti anomali /data/tombstones, logcat o monitorando il fornitore DropboxManager per i bug degli utenti finali. Per ulteriori informazioni sul debug del codice nativo di Android, consulta: le informazioni qui.

Componenti della piattaforma abilitati per MTE

In Android 12, diversi componenti di sistema critici per la sicurezza utilizzano MTE ASYNC rilevare arresti anomali dell'utente finale e fungere da livello aggiuntivo una difesa in profondità. Questi componenti sono:

  • Daemon e utilità di networking (ad eccezione di netd
  • Bluetooth, SecureElement, HAL NFC e app di sistema
  • statsd daemon
  • system_server
  • zygote64 (per consentire alle app di attivare l'utilizzo della funzionalità MTE)

Questi target sono stati selezionati in base ai seguenti criteri:

  • Un processo con privilegi (definito come processo che ha accesso a qualcosa al dominio SELinux unprivileged_app)
  • Elabora un input non attendibile (Regola di due)
  • Rallentamento delle prestazioni accettabile (il rallentamento non rende visibile l'utente latenza)

Invitiamo i fornitori ad abilitare la funzionalità MTE in produzione per più componenti. seguendo i criteri sopra menzionati. Durante lo sviluppo, ti consigliamo di testare questi componenti usando la modalità SYNC, per rilevare bug facilmente risolti e valutare l'impatto di ASYNC sulle prestazioni.
In futuro, Android prevede di ampliare l'elenco dei componenti di sistema dei componenti di sistema attivate, guidata dalle caratteristiche prestazionali dei progetti hardware futuri.