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 dalla policy. Ciò significa che un file di policy è composto da una grande quantità di informazioni relative a regole, tipi, classi, autorizzazioni e altro ancora. Una trattazione completa di SELinux esula dall'ambito di questo documento, ma la comprensione di come scrivere le regole delle policy è ora essenziale quando si utilizzano nuovi dispositivi Android. Sono già disponibili molte informazioni su SELinux. Consulta la documentazione di supporto per le risorse suggerite.
File chiave
Per abilitare SELinux, integra l' ultimo kernel Android e poi incorpora i file che si trovano 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 invece i tuoi file di policy specifici del dispositivo nella
/device/manufacturer/device-name/sepolicy
directory. In Android 8.0 e versioni successive, le modifiche apportate a questi file devono influire solo sulla policy nella directory del fornitore. Per maggiori dettagli sulla separazione della
sepolicy pubblica in Android 8.0 e versioni successive, consulta
Personalizzare SEPolicy in Android
8.0+. Indipendentemente dalla versione di Android, stai comunque modificando questi file:
File di policy
I file che terminano con *.te sono file di origine della policy SELinux, che definiscono i domini e le relative etichette. Potresti dover creare nuovi file di policy in
/device/manufacturer/device-name/sepolicy,
ma dovresti provare ad aggiornare i file esistenti, se possibile.
File di contesto
Nei file di contesto specifichi le etichette per gli oggetti.
file_contextsassegna etichette ai file e viene utilizzato da vari componenti dello spazio utente. Quando crei nuove policy, crea o aggiorna questo file per assegnare nuove etichette ai file. Per applicare nuovifile_contexts, ricompila l'immagine del file system o eseguirestoreconsul file da rietichettare. Durante gli upgrade, le modifiche afile_contextsvengono applicate automaticamente alle partizioni di sistema e dati utente nell'ambito dell' upgrade. Le modifiche possono essere applicate automaticamente anche durante l'upgrade ad altre partizioni aggiungendo chiamaterestorecon_recursiveal file init.board.rc dopo che la partizione è stata montata in lettura/scrittura.genfs_contextsassegna etichette ai file system, comeprocovfatche non supportano gli attributi estesi. Questa configurazione viene caricata come parte della policy del kernel, ma le modifiche potrebbero non avere effetto sugli inode in-core, il che richiede un riavvio o lo smontaggio e il rimontaggio del file system per applicare completamente la modifica. È possibile assegnare etichette specifiche anche a montaggi specifici, ad esempiovfatutilizzando l'context=mountopzione.property_contextsassegna etichette alle proprietà di sistema Android per controllare quali processi possono impostarle. Questa configurazione viene letta dalinitprocesso durante l'avvio.service_contextsassegna 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 dalservicemanagerprocesso durante l'avvio.seapp_contextsassegna etichette ai processi delle app e/data/datadirectory. Questa configurazione viene letta dalzygoteprocesso a ogni avvio dell'app e dainstallddurante l'avvio.mac_permissions.xmlassegna un tagseinfoalle app in base alla loro firma e, facoltativamente, al nome del pacchetto. Ilseinfotag può essere utilizzato come chiave nelseapp_contextsfile per assegnare un'etichetta specifica a tutte le app con quelseinfotag. Questa configurazione viene letta dasystem_serverdurante l'avvio.keystore2_key_contextsassegna etichette agli spazi dei nomi di 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 definiti. Una descrizione dettagliata del formato e delle convenzioni di questo file è disponibile qui.
Makefile BoardConfig.mk
Dopo aver modificato o aggiunto file di policy 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 policy.
Per maggiori 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 policy SELinux per adattarle alle tue aggiunte al sistema operativo Android, come descritto inPersonalizzazione, oppure verificare la configurazione esistente, come descritto inConvalida.
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 maggiori informazioni su come viene creata la sepolicy sul dispositivo, consulta Creazione di sepolicy.
Implementazione
Per iniziare a utilizzare SELinux:
- Abilita SELinux nel kernel:
CONFIG_SECURITY_SELINUX=y - Modifica il parametro kernel_cmdline o bootconfig in modo che:
oBOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
Questa impostazione è valida solo per lo sviluppo iniziale della policy per il dispositivo. Dopo aver creato una policy di bootstrap iniziale, rimuovi questo parametro in modo che il dispositivo applichi la policy o non superi il CTS.BOARD_BOOTCONFIG := androidboot.selinux=permissive
- Avvia il sistema in modalità permissiva e verifica quali rifiuti vengono riscontrati 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 gli avvisi simili a
init: Warning! Service name needs a SELinux domain defined; please fix!Per istruzioni e strumenti, consulta Convalida. - Identifica i dispositivi e gli altri nuovi file che devono essere etichettati.
- Utilizza etichette esistenti o nuove per gli oggetti. Esamina i
*_contextsfile per vedere come sono stati etichettati in precedenza e utilizza la tua conoscenza dei significati delle etichette per assegnarne una nuova. Idealmente, questo è un'etichetta esistente che si adatta alla policy, 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 policy completamente nuova per ciascuno di essi. Ad esempio, tutti i servizi generati da
initdevono avere il proprio dominio. I seguenti comandi consentono di rivelare quelli che rimangono in esecuzione (ma TUTTI servizi necessitano di questo trattamento):
adb shell su -c ps -Z | grep init
adb shell su -c dmesg | grep 'avc: '
- Esamina
init.device.rcper identificare i domini che non hanno un tipo di dominio. Assegna loro un dominio all'inizio della tua procedura di sviluppo per evitare di aggiungere regole ainito di confondere in altro modo gli accessiinitcon quelli che si trovano nella loro policy. - Configura
BOARD_CONFIG.mkin modo che utilizzi le variabiliBOARD_SEPOLICY_*. Per informazioni dettagliate sulla configurazione, consulta il file README insystem/sepolicy. - Esamina il file init.device.rc e fstab.device e assicurati che ogni utilizzo di
mountcorrisponda a un file system etichettato correttamente o che sia specificata un'opzionecontext= mount. - Esamina ogni rifiuto e crea una policy SELinux per gestirlo correttamente. Consulta gli esempi in Personalizzazione.
Devi iniziare con le policy in AOSP e poi svilupparle per le tue personalizzazioni. Per maggiori informazioni sulla strategia delle policy e per un analisi più approfondita di alcuni di questi passaggi, consulta Scrittura della policy SELinux.
Casi d'uso
Ecco esempi specifici di exploit da considerare quando crei il tuo software e le relative policy 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 con privilegi, come init, modificano le autorizzazioni di determinati file, a volte in modo eccessivamente aperto.
Gli utenti malintenzionati potrebbero quindi sostituire questi file con link simbolici al codice che controllano, consentendo loro di sovrascrivere file arbitrari. Tuttavia, 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 il server di sistema stesso.
Con SELinux, puoi identificare questi file come file di dati del server di sistema.
Di conseguenza, l'unico dominio che ha accesso in lettura/scrittura è il server di sistema.
Anche se netd venisse compromesso, non potrebbe passare ai domini 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 devono essere eseguite come root, ma non devono accedere ai dati delle app. Questa funzionalità è incredibilmente utile in quanto è possibile effettuare asserzioni di ampia portata, ad esempio impedire a determinati domini non correlati ai dati delle app di accedere 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 insieme potrebbe essere vietato da queste modifiche, anche da root. Pertanto, un'app potrebbe eseguire chmod e chown sui file etichettati come app_data_files, ma non su shell_data_files o system_data_files.