Implementazione di SELinux

SELinux è impostato su default-deny, 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. Una considerazione completa di SELinux esula dallo scopo di questo documento, ma comprendere come scrivere le regole delle policy è ora essenziale quando si avviano nuovi dispositivi Android. C'è già una grande quantità di informazioni disponibili su SELinux. Consulta la documentazione di supporto per le risorse suggerite.

File chiave

Per abilitare SELinux, integra il kernel Android più recente e quindi incorpora i file trovati nella directory system/sepolicy . Una volta compilati, questi file comprendono la politica di sicurezza del kernel SELinux e coprono il sistema operativo Android upstream.

In generale, non è necessario modificare direttamente i file system/sepolicy . Aggiungi o modifica invece i file delle policy specifiche del dispositivo nella directory /device/ manufacturer / device-name /sepolicy . In Android 8.0 e versioni successive, le modifiche apportate a questi file dovrebbero influire solo sulla policy nella directory del fornitore. Per ulteriori dettagli sulla separazione della sepolicy pubblica in Android 8.0 e versioni successive, vedere Personalizzazione di SEPolicy in Android 8.0 e versioni successive . Indipendentemente dalla versione di Android, stai comunque modificando questi file:

File politici

I file che terminano con *.te sono file sorgente della policy SELinux, che definiscono i domini e le loro etichette. Potrebbe essere necessario creare nuovi file di criteri in /device/ manufacturer / device-name /sepolicy , ma dovresti provare ad aggiornare i file esistenti ove possibile.

File di contesto

I file di contesto sono i luoghi in cui specifichi le etichette per i tuoi oggetti.

  • file_contexts assegna 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 nuovi file_contexts , ricostruire l'immagine del filesystem o eseguire restorecon sul file da rietichettare. Durante gli aggiornamenti, le modifiche a file_contexts vengono applicate automaticamente alle partizioni system e userdata come parte dell'aggiornamento. Le modifiche possono anche essere applicate automaticamente durante l'aggiornamento ad altre partizioni aggiungendo chiamate restorecon_recursive al tuo init. board .rc dopo che la partizione è stata montata in lettura-scrittura.
  • genfs_contexts assegna etichette ai filesystem, come proc o vfat che non supportano attributi estesi. Questa configurazione viene caricata come parte della policy del kernel ma le modifiche potrebbero non avere effetto per gli inode in-core, richiedendo un riavvio o lo smontaggio e rimontaggio del filesystem per applicare completamente la modifica. Etichette specifiche possono anche essere assegnate a montaggi specifici, come vfat utilizzando l'opzione context=mount .
  • property_contexts assegna etichette alle proprietà del sistema Android per controllare quali processi possono impostarle. Questa configurazione viene letta dal processo init durante l'avvio.
  • service_contexts assegna etichette ai servizi di raccoglitore Android per controllare quali processi possono aggiungere (registrare) e trovare (cercare) un riferimento al raccoglitore per il servizio. Questa configurazione viene letta dal processo servicemanager durante l'avvio.
  • seapp_contexts assegna etichette ai processi dell'app e alle directory /data/data . Questa configurazione viene letta dal processo zygote all'avvio di ogni app e da installd durante l'avvio.
  • mac_permissions.xml assegna un tag seinfo alle app in base alla loro firma e facoltativamente al nome del pacchetto. Il tag seinfo può quindi essere utilizzato come chiave nel file seapp_contexts per assegnare un'etichetta specifica a tutte le app con quel tag seinfo . Questa configurazione viene letta da system_server durante l'avvio.
  • keystore2_key_contexts assegna etichette agli spazi dei nomi Keystore 2.0. Questi spazi dei nomi vengono applicati dal demone keystore2. Il keystore ha sempre fornito spazi dei nomi basati su UID/AID. Keystore 2.0 applica inoltre gli spazi dei nomi definiti dalla sepolicy. Una descrizione dettagliata del formato e delle convenzioni di questo file può essere trovata qui .

Makefile BoardConfig.mk

Dopo aver modificato o aggiunto i file di policy e di contesto, aggiorna il tuo makefile /device/ manufacturer / device-name /BoardConfig.mk per fare riferimento alla sottodirectory sepolicy e a ogni nuovo file di policy. Per ulteriori informazioni sulle variabili BOARD_SEPOLICY , consultare 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 tuo dispositivo è abilitato con SELinux. Ora puoi personalizzare le tue policy SELinux per accogliere le tue aggiunte al sistema operativo Android come descritto in Personalizzazione o verificare la tua configurazione esistente come trattato in Convalida .

Una volta implementati i nuovi file di policy e gli aggiornamenti di BoardConfig.mk, le nuove impostazioni di policy vengono automaticamente integrate nel file di policy del kernel finale. Per ulteriori informazioni su come viene creata la sepolicy nel dispositivo, vedere Creazione di sepolicy .

Implementazione

Per iniziare con SELinux:

  1. Abilita SELinux nel kernel: CONFIG_SECURITY_SELINUX=y
  2. Modificare il parametro kernel_cmdline o bootconfig in modo che:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    o
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    Questo è solo per lo sviluppo iniziale della policy per il dispositivo. Dopo aver definito una policy di bootstrap iniziale, rimuovi questo parametro in modo che il tuo dispositivo applichi altrimenti CTS non riuscirà.
  3. Avvia il sistema in modalità permissiva e controlla quali rifiuti vengono riscontrati all'avvio:
    Su Ubuntu 14.04 o successivo:
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
    
    Su Ubuntu 12.04:
    adb pull /sys/fs/selinux/policy
    adb logcat -b all | audit2allow -p policy
    
  4. Valuta l'output per gli avvisi che assomigliano init: Warning! Service name needs a SELinux domain defined; please fix! Vedere Convalida per istruzioni e strumenti.
  5. Identifica i dispositivi e altri nuovi file che necessitano di etichettatura.
  6. Utilizza etichette esistenti o nuove per i tuoi oggetti. Guarda i file *_contexts per vedere come le cose erano precedentemente etichettate e usa la conoscenza dei significati delle etichette per assegnarne una nuova. Idealmente, si tratterà di un’etichetta esistente che si adatterà alla politica, ma a volte sarà necessaria una nuova etichetta e saranno necessarie regole per l’accesso a quell’etichetta. Aggiungi le tue etichette ai file di contesto appropriati.
  7. Identificare domini/processi che dovrebbero avere i propri domini di sicurezza. Probabilmente dovrai scrivere una politica completamente nuova per ciascuno. Tutti i servizi generati da init , ad esempio, dovrebbero avere il proprio. I seguenti comandi aiutano a rivelare quelli che rimangono in esecuzione (ma TUTTI i servizi necessitano di tale trattamento):
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. Rivedi init. device .rc per identificare eventuali domini che non hanno un tipo di dominio. Assegna loro un dominio all'inizio del processo di sviluppo per evitare di aggiungere regole a init o confondere in altro modo gli accessi init con quelli che sono nella loro stessa policy.
  9. Configura BOARD_CONFIG.mk per utilizzare le variabili BOARD_SEPOLICY_* . Consulta il file README in system/sepolicy per i dettagli sulla configurazione.
  10. Esaminare il file init. device .rc e fstab. device e assicurarsi che ogni utilizzo di mount corrisponda a un filesystem etichettato correttamente o che sia specificata un'opzione context= mount .
  11. Esamina ogni rifiuto e crea la policy SELinux per gestirli correttamente. Vedere gli esempi in Personalizzazione .

Dovresti iniziare con le policy nell'AOSP e poi basarti su di esse per le tue personalizzazioni. Per ulteriori informazioni sulla strategia politica e uno sguardo più attento ad alcuni di questi passaggi, vedere Scrittura della politica SELinux .

Casi d'uso

Ecco alcuni esempi specifici di exploit da considerare quando si crea il proprio software e le policy SELinux associate:

Collegamenti simbolici : poiché i collegamenti simbolici vengono visualizzati come file, vengono spesso letti come file, il che può portare a exploit. Ad esempio, alcuni componenti privilegiati, come init , modificano i permessi di determinati file, a volte rendendoli eccessivamente aperti.

Gli aggressori potrebbero quindi sostituire quei file con collegamenti simbolici al codice che controllano, consentendo all'aggressore di sovrascrivere file arbitrari. Ma se sai che la tua applicazione non attraverserà mai un collegamento simbolico, puoi impedirgli di farlo con SELinux.

File di sistema : considera la classe di file di sistema che dovrebbero essere modificati solo dal server di sistema. Tuttavia, poiché netd , init e vold vengono eseguiti come root, possono accedere a tali file di sistema. Quindi, se netd venisse compromesso, potrebbe compromettere quei 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 ad essi è il server di sistema. Anche se netd venisse compromesso, non potrebbe cambiare dominio al dominio del server di sistema e accedere a quei file di sistema sebbene venga eseguito come root.

Dati dell'app : un altro esempio è la classe di funzioni che devono essere eseguite come root ma non dovrebbero accedere ai dati dell'app. Ciò è incredibilmente utile poiché è possibile fare affermazioni di ampia portata, ad esempio vietando l'accesso a Internet a determinati domini non correlati ai dati dell'applicazione.

setattr - Per comandi come chmod e chown , è possibile identificare l'insieme di file in cui il dominio associato può eseguire setattr . Qualsiasi cosa al di fuori di ciò potrebbe essere vietata da queste modifiche, anche da root. Quindi un'applicazione potrebbe eseguire chmod e chown contro quelli etichettati app_data_files ma non shell_data_files o system_data_files .