Memoria di sola esecuzione (XOM) per i file binari AArch64

Le sezioni di codice eseguibili per i file binari di sistema AArch64 sono contrassegnate per impostazione predefinita solo esecuzione (non leggibile) come mitigazione di protezione avanzata contro il codice just-in-time e riutilizzare gli attacchi. Codice che combina dati e codice e che lo modifica intenzionalmente esamina queste sezioni (senza prima rimappare i segmenti di memoria come leggibili) non funzionano più. App con SDK target pari a 10 (livello API 29 o superiore) sono interessati se l'app tenta di leggere sezioni di codice di librerie di sistema abilitate per la memoria di sola esecuzione (XOM) in memoria contrassegnando la sezione come leggibile.

Per trarre il massimo vantaggio da questa mitigazione, sia il supporto hardware che kernel sono obbligatorio. Senza questo supporto, la mitigazione potrebbe essere applicata solo parzialmente. La Il kernel comune di Android 4.9 contiene le patch appropriate per fornire per i dispositivi ARMv8.2.

Implementazione

I file binari AArch64 generati dal compilatore presuppongono che il codice e i dati non siano mescolati. L'attivazione di questa funzione non influisce negativamente sulle prestazioni di del dispositivo.

Per il codice che deve eseguire introspezione intenzionale della memoria sul suo segmenti eseguibili, è consigliabile chiamare mprotect sul segmenti di codice che richiedono un'ispezione per consentirne la lettura, quindi rimuovere la leggibilità al termine dell'ispezione.
Questa implementazione fa sì che le letture nei segmenti di memoria contrassegnati come solo di esecuzione per generare un errore di segmentazione (SEGFAULT). Ciò potrebbe verificarsi a causa di un bug, una vulnerabilità, dati mescolati con (pooling letterale) o introspezione intenzionale della memoria.

Supporto e impatto dei dispositivi

I dispositivi con hardware precedenti o kernel precedenti (inferiori alla 4.9) senza le patch richieste potrebbero non supportare completamente questa funzionalità o trarre vantaggio da questa funzionalità. Dispositivi senza il supporto del kernel non possono imporre gli accessi degli utenti alla memoria di sola esecuzione, tuttavia il codice kernel che controlla esplicitamente se una pagina è leggibile può applicare in modo forzato questa proprietà, ad esempio process_vm_readv().

Il flag del kernel CONFIG_ARM64_UAO deve essere impostato nel kernel su assicurarsi che il kernel rispetti le pagine userland contrassegnate con il valore di sola esecuzione. ARMv8 precedente i dispositivi o i dispositivi ARMv8.2 con User Access Override (UAO) disabilitato, potrebbero non sfruttano al massimo questa funzionalità e potrebbero essere ancora in grado di leggere le pagine di sola esecuzione utilizzando syscall.

Esegui il refactoring del codice esistente

Il codice che è stato trasferito da AArch32 potrebbe contenere dati mescolati e codice, causando problemi. In molti casi, risolvere questi problemi è semplice come lo spostamento delle costanti in una sezione .data del file di assemblaggio.

Potrebbe essere necessario il refactoring dell'assemblaggio scritto a mano per separare l'assemblaggio in un pool locale costanti.

Esempi:

I file binari generati dal compilatore Clang non dovrebbero avere problemi con i dati mescolati nel codice. Se il codice generato dalla GNU compilatore (GCC) viene inclusi (da una libreria statica), esamina il file binario di output per assicurarti che le costanti non siano state raggruppate nelle sezioni di codice.

Se è necessaria l'introspezione del codice nelle sezioni di codice eseguibili, prima chiama mprotect per contrassegnare il codice come leggibile. Dopo l'operazione è completa, chiama di nuovo mprotect per contrassegnarla come illeggibile.

Abilita XOM

L'opzione Solo esecuzione è abilitata per impostazione predefinita per tutti i file binari a 64 bit nella build di un sistema operativo completo.

Disabilita XOM

È possibile disattivare l'esecuzione solo a livello di modulo, da un'intera struttura di sottodirectory oppure a livello globale per un'intera build.

È possibile disabilitare XOM per singoli moduli che non possono essere sottoposti a refactoring o che devono essere letti di codice eseguibile impostando il valore LOCAL_XOM e xom in false.

// Android.mk
LOCAL_XOM := false

// Android.bp
cc_binary { // or other module types
   ...
   xom: false,
}

Se la memoria di sola esecuzione è disabilitata in una libreria statica, il sistema di compilazione applica a tutti i moduli dipendenti di quella libreria statica. Puoi eseguire l'override utilizzando xom: true,.

Per disattivare la memoria di sola esecuzione in una determinata sottodirectory (ad esempio, foo/bar/), passa il valore a XOM_EXCLUDE_PATHS.

make -j XOM_EXCLUDE_PATHS=foo/bar

In alternativa, puoi impostare PRODUCT_XOM_EXCLUDE_PATHS nella configurazione del prodotto.

Puoi disabilitare globalmente i file binari di sola esecuzione passandoli ENABLE_XOM=false al comando make.

make -j ENABLE_XOM=false

Convalida

Non sono disponibili test CTS o di verifica solo per l'esecuzione la memoria. Puoi verificare manualmente i file binari utilizzando readelf e controllando i flag del segmento.