SELinux è configurato per il rifiuto predefinito, il che significa che ogni singolo accesso per il quale ha un hook nel kernel deve essere esplicitamente consentito dai criteri. Ciò significa che un file di policy è costituito da una grande quantità di informazioni relative a regole, tipi, classi, autorizzazioni e altro ancora. Una trattazione completa di SELinux non rientra nell'ambito di questo documento, ma la comprensione di come scrivere le regole delle policy è ora essenziale quando si configurano nuovi dispositivi Android. Esistono già molte informazioni su SELinux. Consulta la documentazione di supporto per le risorse suggerite.
File di chiave
Per attivare SELinux, integra l'ultimo kernel Android e poi incorpora i file trovati nella directory system/sepolicy. Una volta compilati, questi file comprendono la policy di sicurezza del kernel SELinux e coprono il sistema operativo Android upstream.
In generale, non devi modificare direttamente i file system/sepolicy
. Aggiungi o modifica i tuoi file di policy specifici per il dispositivo nella directory
/device/manufacturer/device-name/sepolicy
. In Android 8.0 e versioni successive, le modifiche apportate a questi file devono
influire solo sui criteri nella directory del fornitore. Per ulteriori dettagli sulla separazione di
sepolicy pubblica in Android 8.0 e versioni successive, consulta
Personalizzazione di SEPolicy in Android
8.0+. Indipendentemente dalla versione di Android, devi comunque modificare questi file:
File dei criteri
I file che terminano con *.te
sono file di origine delle policy SELinux, che
definiscono i domini e le relative etichette. Potresti dover creare nuovi file delle norme in
/device/manufacturer/device-name/sepolicy
,
ma dovresti provare ad aggiornare i file esistenti, se possibile.
File di contesto
I file di contesto sono i file in cui specifichi le etichette per gli oggetti.
file_contexts
assegna etichette ai file e viene utilizzato da vari componenti dello spazio utente. Man mano che crei nuove norme, crea o aggiorna questo file per assegnare nuove etichette ai file. Per applicare nuovefile_contexts
, ricostruisci l'immagine del file system o eseguirestorecon
sul file da rietichettare. Durante gli upgrade, le modifiche afile_contexts
vengono applicate automaticamente alle partizioni di sistema e dati utente nell'ambito dell'upgrade. Le modifiche possono essere applicate automaticamente anche all'upgrade ad altre partizioni aggiungendo chiamaterestorecon_recursive
al file init.board.rc dopo che la partizione è stata montata in lettura/scrittura.genfs_contexts
assegna etichette ai file system, ad esempioproc
ovfat
che non supportano gli attributi estesi. Questa configurazione viene caricata come parte della policy del kernel, ma le modifiche potrebbero non essere applicate agli inode in-core, richiedendo un riavvio o lo smontaggio e il rimontaggio del file system per applicare completamente la modifica. Etichette specifiche possono essere assegnate anche a supporti specifici, ad esempiovfat
utilizzando l'opzionecontext=mount
.property_contexts
assegna etichette alle proprietà di sistema Android per controllare quali processi possono impostarle. Questa configurazione viene letta dal processoinit
durante l'avvio.service_contexts
assegna etichette ai servizi binder Android per controllare quali processi possono aggiungere (registrare) e trovare (cercare) un riferimento binder per il servizio. Questa configurazione viene letta dal processoservicemanager
durante l'avvio.seapp_contexts
assegna etichette ai processi delle app e alle directory/data/data
. Questa configurazione viene letta dal processozygote
a ogni avvio dell'app e dainstalld
durante l'avvio.mac_permissions.xml
assegna un tagseinfo
alle app in base alla loro firma e, facoltativamente, al nome del pacchetto. Il tagseinfo
può quindi essere utilizzato come chiave nel fileseapp_contexts
per assegnare un'etichetta specifica a tutte le app con quel tagseinfo
. Questa configurazione viene letta dasystem_server
all'avvio.keystore2_key_contexts
assegna etichette agli spazi dei nomi Keystore 2. Questi spazi dei nomi vengono applicati dal daemonkeystore2
. Keystore ha sempre fornito spazi dei nomi basati su UID/AID. Keystore 2 applica inoltre gli spazi dei nomi definiti da sepolicy. Una descrizione dettagliata del formato e delle convenzioni di questo file è disponibile qui.
Makefile BoardConfig.mk
Dopo aver modificato o aggiunto i file di criteri e di contesto, aggiorna il
/device/manufacturer/device-name/BoardConfig.mk
makefile in modo che faccia riferimento alla sottodirectory sepolicy
e a ogni nuovo file di criteri.
Per ulteriori informazioni sulle variabili BOARD_SEPOLICY
, consulta il
file
system/sepolicy/README
.
BOARD_SEPOLICY_DIRS += \ <root>/device/manufacturer/device-name/sepolicy BOARD_SEPOLICY_UNION += \ genfs_contexts \ file_contexts \ sepolicy.te
Dopo la ricompilazione, SELinux è abilitato sul dispositivo. Ora puoi personalizzare le tue norme SELinux per adattarle alle tue aggiunte al sistema operativo Android come descritto in Personalizzazione o verificare la tua configurazione esistente come descritto in Convalida.
Quando i nuovi file di policy e gli aggiornamenti di BoardConfig.mk sono in vigore, le nuove impostazioni delle policy vengono integrate automaticamente nel file di policy del kernel finale. Per saperne di più su come viene creata sepolicy sul dispositivo, vedi Creazione di sepolicy.
Implementazione
Per iniziare a utilizzare SELinux:
- Attiva SELinux nel kernel:
CONFIG_SECURITY_SELINUX=y
- Modifica il parametro kernel_cmdline o bootconfig in modo che:
oppureBOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
Questo vale solo per lo sviluppo iniziale delle norme per il dispositivo. Dopo aver creato un criterio di bootstrap iniziale, rimuovi questo parametro in modo che il dispositivo lo applichi o CTS non vada a buon fine.BOARD_BOOTCONFIG := androidboot.selinux=permissive
- Avvia il sistema in modalità permissiva e verifica quali errori di negazione si verificano all'avvio:
Su Ubuntu 14.04 o versioni successive: Su Ubuntu 12.04:adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
adb pull /sys/fs/selinux/policy adb logcat -b all | audit2allow -p policy
- Valuta l'output per individuare avvisi simili a
init: Warning! Service name needs a SELinux domain defined; please fix!
. Consulta la sezione Convalida per istruzioni e strumenti. - Identifica i dispositivi e gli altri nuovi file che devono essere etichettati.
- Utilizza etichette esistenti o nuove per gli oggetti. Esamina i file
*_contexts
per vedere come sono stati etichettati in precedenza e utilizza la conoscenza dei significati delle etichette per assegnarne una nuova. Idealmente, si tratta di un'etichetta esistente che rientra nelle norme, ma a volte è necessaria una nuova etichetta e sono necessarie regole per l'accesso a questa etichetta. Aggiungi le etichette ai file di contesto appropriati. - Identifica i domini/processi che devono avere i propri domini di sicurezza.
Probabilmente dovrai scrivere una norma completamente nuova per ciascuna. Tutti
i servizi generati da
init
, ad esempio, devono avere il proprio. I seguenti comandi consentono di rivelare quelli che rimangono in esecuzione (ma TUTTI i servizi necessitano di questo trattamento):
adb shell su -c ps -Z | grep init
adb shell su -c dmesg | grep 'avc: '
- Esamina
init.device.rc
per identificare i domini che non hanno un tipo di dominio. Assegna loro un dominio all'inizio del processo di sviluppo per evitare di aggiungere regole ainit
o di confondere in altro modo gli accessi ainit
con quelli presenti nelle loro norme. - Configura
BOARD_CONFIG.mk
per utilizzare le variabiliBOARD_SEPOLICY_*
. Per informazioni dettagliate sulla configurazione, consulta il README insystem/sepolicy
. - Esamina i file init.device.rc e fstab.device e
assicurati che ogni utilizzo di
mount
corrisponda a un file system etichettato correttamente o che sia specificata un'opzionecontext= mount
. - Esamina ogni negazione e crea criteri SELinux per gestirli correttamente. Consulta gli esempi in Personalizzazione.
Dovresti iniziare con le norme dell'AOSP e poi basarti su queste per le tue personalizzazioni. Per ulteriori informazioni sulla strategia delle policy e per un'analisi più approfondita di alcuni di questi passaggi, consulta Scrittura di policy SELinux.
Casi d'uso
Ecco alcuni esempi specifici di exploit da considerare quando crei il tuo software e le relative norme SELinux:
Link simbolici: poiché i link simbolici vengono visualizzati come file, spesso
vengono letti come file, il che può portare a exploit. Ad esempio, alcuni componenti privilegiati, come init
, modificano le autorizzazioni di determinati file, a volte in modo eccessivamente aperto.
Gli autori dell'attacco potrebbero quindi sostituire questi file con collegamenti simbolici al codice che controllano, consentendo loro di sovrascrivere file arbitrari. Ma se sai che la tua app non attraversa mai un link simbolico, puoi impedirglielo con SELinux.
File di sistema:considera la classe di file di sistema che
devono essere modificati solo dal server di sistema. Tuttavia, poiché netd
,
init
e vold
vengono eseguiti come root, possono accedere
a questi file di sistema. Pertanto, se netd
venisse compromesso, potrebbe
compromettere questi file e potenzialmente lo stesso server di sistema.
Con SELinux, puoi identificare questi file come file di dati del server di sistema.
Pertanto, l'unico dominio che ha accesso in lettura/scrittura è il server di sistema.
Anche se netd
venisse compromesso, non potrebbe passare al dominio del server di sistema e accedere a questi file di sistema, anche se viene eseguito come root.
Dati delle app:un altro esempio è la classe di funzioni che deve essere eseguita come root, ma non deve accedere ai dati delle app. Questa funzionalità è incredibilmente utile perché consente di fare asserzioni di ampia portata, ad esempio che a determinati domini non correlati ai dati delle app è vietato l'accesso a internet.
setattr:per comandi come chmod
e
chown
, puoi identificare l'insieme di file in cui il dominio associato può eseguire setattr
. Qualsiasi elemento al di fuori di questo potrebbe essere
proibito da queste modifiche, anche da root. Pertanto, un'app potrebbe eseguire
chmod
e chown
rispetto a quelle etichettate
app_data_files
, ma non shell_data_files
o system_data_files
.