Implementazione di SELinux

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

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 criteri è 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 la comprensione di come scrivere le regole dei criteri è ora essenziale quando si attivano nuovi dispositivi Android. Ci sono già molte informazioni disponibili su SELinux. Vedere 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 a monte.

In generale, non dovresti modificare direttamente i file di system/sepolicy . Invece, aggiungi o modifica i tuoi file di criteri specifici 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 sui criteri nella directory del fornitore. Per ulteriori dettagli sulla separazione della privacy 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 ancora modificando questi file:

File delle politiche

I file che terminano con *.te sono file di origine delle politiche SELinux, che definiscono i domini e le relative 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 dove specifichi le etichette per i tuoi oggetti.

  • file_contexts assegna etichette ai file e viene utilizzato da vari componenti dello spazio utente. Quando crei nuovi criteri, 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 di sistema e dati utente come parte dell'aggiornamento. Le modifiche possono anche essere applicate automaticamente all'aggiornamento ad altre partizioni aggiungendo le 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 politica 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 mount specifici, come vfat usando 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 raccoglitore Android per controllare quali processi possono aggiungere (registrare) e trovare (cercare) un riferimento 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 ad ogni avvio dell'app e 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 sono applicati dal demone keystore2. 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 .

File di configurazione BoardConfig.mk

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

Quando i nuovi file delle politiche e gli aggiornamenti di BoardConfig.mk sono a posto, le nuove impostazioni delle politiche vengono automaticamente integrate nel file delle politiche del kernel finale. Per ulteriori informazioni sulla modalità di creazione di sepolicy sul 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 politica per il dispositivo. Dopo aver stabilito un criterio di bootstrap iniziale, rimuovere questo parametro in modo che il dispositivo stia applicando o non riuscirà CTS.
  3. Avvia il sistema in modo permissivo e guarda quali rifiuti vengono incontrati all'avvio:
    Su Ubuntu 14.04 o versioni successive:
    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 a 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. Usa 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 dell'etichetta 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 tale etichetta. Aggiungi le tue etichette ai file di contesto appropriati.
  7. Identificare i 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 i propri. I seguenti comandi aiutano a rivelare quelli che rimangono in esecuzione (ma TUTTI i servizi richiedono un tale trattamento):
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. Esamina init. device .rc per identificare tutti i 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 di confondere in altro modo gli accessi init con quelli che sono nella loro stessa politica.
  9. Configura BOARD_CONFIG.mk per utilizzare le variabili BOARD_SEPOLICY_* . Vedere il README in system/sepolicy per i dettagli sulla configurazione.
  10. Esaminare l'inizializzazione. device .rc e fstab. device e assicurati che ogni uso di mount corrisponda a un filesystem etichettato correttamente o che sia specificata un'opzione context= mount .
  11. Esamina ogni rifiuto e crea una politica SELinux per gestirli correttamente. Vedere gli esempi in Personalizzazione .

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

Casi d'uso

Ecco alcuni esempi specifici di exploit da considerare quando si crea il proprio software e le politiche 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 per essere eccessivamente aperti.

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

File di sistema - Considera la classe dei 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 quei file di sistema. Quindi, se netd è stato compromesso, potrebbe compromettere quei file e potenzialmente il server di sistema stesso.

Con SELinux, puoi identificare quei 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 è stato compromesso, non potrebbe cambiare i domini nel 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 devono accedere ai dati dell'app. Ciò è incredibilmente utile in quanto è possibile fare affermazioni ad ampio raggio, come ad esempio il divieto di 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ò condurre 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 su quelli etichettati app_data_files ma non shell_data_files o system_data_files .