ARM v9 introduce la memoria ARM Tagging Extension (MTE), un'implementazione hardware di con un tag di memoria.
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. Ciò 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 abilitata, la funzionalità 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 una memoria 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
.
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
).
Puoi trovarli 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 includi un'analisi dello stack di allocazione o deallocation. Queste analisi dello stack vengono 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 la modifica dei 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 riesce a 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 hardware
PSTATE.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 parametroSA_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
.
- la raccolta delle analisi dello stack richiede anche
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.
Utilizzo consigliato
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
daemonsystem_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.