SELinux è configurato per il rifiuto predefinito, il che significa che ogni singolo accesso per il quale è presente un hook nel kernel deve essere consentito esplicitamente dal criterio. Ciò significa che un file di criteri è costituito da una grande quantità di informazioni su regole, tipi, classi, autorizzazioni e altro ancora. Un'analisi completa di SELinux rientra al di fuori dell'ambito di questo documento, ma comprendere come scrivere le regole delle norme è ora essenziale per l'utilizzo di nuovi dispositivi Android. Esistono già moltissime informazioni su SELinux. Consulta la documentazione di supporto per le risorse suggerite.
File principali
Per attivare SELinux, integra il kernel Android più recente e poi incorpora i file trovati nella directory system/sepolicy. Una volta compilati, questi file comprendono i criteri 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 criteri specifici per il dispositivo nella directory/device/manufacturer/device-name/sepolicy
. In Android 8.0 e versioni successive, le modifiche apportate a questi file dovrebbero riguardare solo i criteri nella directory del fornitore. Per ulteriori dettagli sulla separazione di sepolicy pubblico in Android 8.0 e versioni successive, consulta Personalizzazione di SEPolicy in Android 8.0 e versioni successive. Indipendentemente dalla versione di Android, dovrai comunque modificare questi file:
File di criteri
I file che terminano con *.te
sono file di origine dei criteri SELinux, che
definiscono i domini e le relative etichette. Potresti dover creare nuovi file di norme in
/device/manufacturer/device-name/sepolicy
,
ma, se possibile, dovresti provare ad aggiornare i file esistenti.
File di contesto
Nei file di contesto 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 nuovi criteri, crea o aggiorna questo file per assegnare nuove etichette ai file. Per applicare un nuovofile_contexts
, ricostruisci l'immagine del file system o eseguirestorecon
sul file da rinominare. Durante gli upgrade, le modifiche afile_contexts
vengono applicate automaticamente alle partizioni system e userdata nell'ambito dell'upgrade. Le modifiche possono essere applicate automaticamente anche durante l'upgrade ad altre partizioni aggiungendo chiamaterestorecon_recursive
al file init.board.rc dopo aver montato la partizione in modalità di lettura/scrittura.genfs_contexts
assegna etichette ai file system, comeproc
ovfat
, che non supportano gli attributi estesi. Questa configurazione viene caricata come parte del criterio del kernel, ma le modifiche potrebbero non essere applicate agli inode in-core, richiedendo un riavvio o smontaggio e rimontaggio del file system per applicare completamente la modifica. È possibile assegnare etichette specifiche 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 di 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 e alle directory/data/data
dell'app. 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ò essere utilizzato come chiave nel fileseapp_contexts
per assegnare un'etichetta specifica a tutte le app con questo tagseinfo
. Questa configurazione viene letta dasystem_server
durante l'avvio.keystore2_key_contexts
assegna le etichette agli spazi dei nomi Keystore 2.0. Questi spazi dei nomi vengono applicati dal daemon keystore2. Il keystore ha sempre fornito spazi dei nomi basati su UID/AID. Keystore 2.0 applica inoltre gli spazi dei nomi definiti da sepolicy. Una descrizione dettagliata del formato e delle convenzioni di questo file è disponibile qui.
File 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 ricostruzione, il dispositivo è abilitato con SELinux. Ora puoi personalizzare i tuoi criteri SELinux per adattarli alle tue aggiunte al sistema operativo Android, come descritto in Personalizzazione, oppure verificare la configurazione esistente, come descritto in Convalida.
Quando i nuovi file di criteri e gli aggiornamenti di BoardConfig.mk sono in atto, le nuove impostazioni dei criteri vengono integrate automaticamente nel file di criteri del kernel finale. Per ulteriori informazioni su come viene creato sepolicy sul dispositivo, consulta 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 dei criteri per il dispositivo. Dopo aver definito un criterio di bootstrap iniziale, rimuovi questo parametro in modo che il dispositivo lo applichi o non superi il CTS.BOARD_BOOTCONFIG := androidboot.selinux=permissive
- Avvia il sistema in modalità permissiva e controlla quali negazioni vengono rilevate 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 verificare la presenza di 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 erano etichettate le risorse in precedenza e utilizza la conoscenza dei significati delle etichette per assegnarne una nuova. Idealmente, si tratta di un'etichetta esistente che rispetta i criteri, ma a volte è necessaria una nuova etichetta e sono necessarie regole per l'accesso a quell'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 ogni canale. Ad esempio, tutti i servizi generati da
init
devono avere il proprio. I seguenti comandi consentono di rilevare quelli che rimangono in esecuzione (ma TUTTI i servizi richiedono 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. Assegnagli un dominio all'inizio del processo di sviluppo per evitare di aggiungere regole ainit
o di confondere gli accessi ainit
con quelli previsti dalle sue norme. - Configura
BOARD_CONFIG.mk
in modo da utilizzare le variabiliBOARD_SEPOLICY_*
. Per informazioni dettagliate sulla configurazione, consulta il file README insystem/sepolicy
. - Esamina i file init.device.rc e fstab.device e
assicurati che ogni utilizzo di
mount
corrisponda a un filesystem correttamente etichettato o che sia specificata un'opzionecontext= mount
. - Esamina ogni rifiuto e crea un criterio SELinux per gestirlo correttamente. Consulta gli esempi in Personalizzazione.
Dovresti iniziare con le norme nell'AOSP e poi svilupparle per le tue personalizzazioni. Per ulteriori informazioni sulla strategia di criteri e per approfondire alcuni di questi passaggi, consulta Scrivere i criteri SELinux.
Casi d'uso
Ecco alcuni esempi specifici di exploit da considerare quando crei il tuo software e i relativi criteri SELinux:
Link simbolici: poiché i link simbolici appaiono come file, spesso vengonoletti 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 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 vietarlo con SELinux.
File di sistema:prendi in considerazione la classe di file di sistema che deve essere modificata 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
viene 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.
Pertanto, l'unico dominio che ha accesso in lettura/scrittura è il server di sistema.
Anche se netd
fosse stato compromesso, non avrebbe potuto cambiare dominio con il dominio del server di sistema e accedere a questi file di sistema, anche se viene eseguito come utente root.
Dati dell'app:un altro esempio è la classe di funzioni che deve essere eseguita come root, ma non deve accedere ai dati dell'app. Questo è incredibilmente utile perché è possibile fare affermazioni di ampio respiro, ad esempio vietare 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
. Tutto ciò che non rientra in questo ambito potrebbe essere vietato da queste modifiche, anche dall'utente root. Pertanto, un'app potrebbe eseguire chmod
e chown
su quelle etichettate come app_data_files
, ma non su shell_data_files
o system_data_files
.