Costruire una politica SELinux

Questo articolo spiega come viene creata la policy SELinux. La policy SELinux è costruita dalla combinazione della policy AOSP principale (piattaforma) e della policy specifica del dispositivo (fornitore). Il flusso di creazione della policy SELinux per Android da 4.4 a Android 7.0 ha unito tutti i frammenti di sepolicy, quindi ha generato file monolitici nella directory root. Ciò significava che i fornitori di SoC e i produttori di ODM modificavano boot.img (per dispositivi non A/B) o system.img (per dispositivi A/B) ogni volta che la policy veniva modificata.

In Android 8.0 e versioni successive, i criteri relativi alla piattaforma e al fornitore vengono creati separatamente. I SOC e gli OEM possono aggiornare le proprie parti della policy, creare le proprie immagini (ad esempio, vendor.img e boot.img ), quindi aggiornare tali immagini indipendentemente dagli aggiornamenti della piattaforma.

Tuttavia, poiché i file di policy SELinux modularizzati sono archiviati su partizioni /vendor , il processo init deve montare prima le partizioni di sistema e quelle del fornitore in modo da poter leggere i file SELinux da quelle partizioni e unirli con i file principali di SELinux nella directory di sistema (prima di caricarli in il nocciolo).

File sorgenti

La logica per costruire SELinux è in questi file:

  • external/selinux : progetto SELinux esterno, utilizzato per creare utilità della riga di comando HOST per compilare policy ed etichette SELinux.
    • external/selinux/libselinux : Android utilizza solo un sottoinsieme del progetto libselinux esterno insieme ad alcune personalizzazioni specifiche di Android. Per i dettagli, vedere external/selinux/README.android .
    • external/selinux/libsepol :
      • chkcon : determina se un contesto di sicurezza è valido per una determinata policy binaria (eseguibile host).
      • libsepol : libreria SELinux per manipolare le politiche di sicurezza binarie (libreria host statica/condivisa, libreria statica di destinazione).
    • external/selinux/checkpolicy : compilatore di policy SELinux (eseguibili host: checkpolicy , checkmodule e dispol ). Dipende da libsepol .
  • system/sepolicy : configurazioni principali dei criteri Android SELinux, inclusi contesti e file dei criteri. Anche la logica di creazione della sepolicy principale è presente qui ( system/sepolicy/Android.mk ).

Per maggiori dettagli sui file in system/sepolicy Implementing SELinux .

Android 7.0 e versioni precedenti

Questa sezione illustra il modo in cui la policy SELinux viene creata in Android 7.x e versioni precedenti.

Costruire la politica SELinux

La policy SELinux viene creata combinando la policy AOSP principale con personalizzazioni specifiche del dispositivo. La policy combinata viene quindi passata al compilatore della policy e a vari controllori. La personalizzazione specifica del dispositivo viene eseguita tramite la variabile BOARD_SEPOLICY_DIRS definita nel file Boardconfig.mk specifico del dispositivo. Questa variabile di build globale contiene un elenco di directory che specificano l'ordine in cui cercare file di policy aggiuntivi.

Ad esempio, un fornitore di SoC e un ODM potrebbero aggiungere ciascuno una directory, una per le impostazioni specifiche del SoC e un'altra per le impostazioni specifiche del dispositivo, per generare le configurazioni SELinux finali per un determinato dispositivo:

  • BOARD_SEPOLICY_DIRS += device/ SOC /common/sepolicy
  • BOARD_SEPOLICY_DIRS += device/ SoC / DEVICE /sepolicy

Il contenuto dei file file_contexts in system/sepolicy e BOARD_SEPOLICY_DIRS viene concatenato per generare file_contexts.bin sul dispositivo:

Questa immagine mostra la logica di compilazione di SELinux per Android 7.x.
Figura 1 . Logica di costruzione di SELinux

Il file sepolicy è costituito da più file di origine:

  • Il policy.conf in testo semplice viene generato concatenando security_classes , initial_sids , file *.te , genfs_contexts e port_contexts in quest'ordine.
  • Per ogni file (come security_classes ), il suo contenuto è la concatenazione dei file con lo stesso nome in system/sepolicy/ e BOARDS_SEPOLICY_DIRS .
  • Il policy.conf viene inviato al compilatore SELinux per il controllo della sintassi e compilato in formato binario come sepolicy sul dispositivo.
    Questa immagine mostra i file che generano il file dei criteri SELinux per Android 7.x.
    Figura 2 . File dei criteri SELinux

File SELinux

Dopo la compilazione, i dispositivi Android con versione 7.x e versioni precedenti in genere contengono i seguenti file relativi a SELinux:

  • selinux_version
  • sepolicy: output binario dopo aver combinato i file di policy (come security_classes , initial_sids e *.te )
  • file_contexts
  • property_contexts
  • seapp_contexts
  • service_contexts
  • system/etc/mac_permissions.xml

Per maggiori dettagli, vedere Implementazione di SELinux .

Inizializzazione di SELinux

Quando il sistema si avvia, SELinux è in modalità permissiva (e non in modalità di applicazione). Il processo init esegue le seguenti attività:

  • Carica i file sepolicy dal ramdisk nel kernel tramite /sys/fs/selinux/load .
  • Passa SELinux alla modalità di applicazione.
  • Esegue re-exec() per applicare la regola del dominio SELinux a se stesso.

Per ridurre il tempo di avvio, eseguire re-exec() sul processo init il prima possibile.

Android 8.0 e versioni successive

In Android 8.0, la policy SELinux è suddivisa in componenti della piattaforma e del fornitore per consentire aggiornamenti indipendenti della policy della piattaforma/fornitore mantenendo la compatibilità.

La sepolicy della piattaforma è ulteriormente suddivisa in parti private e pubbliche della piattaforma per esportare tipi e attributi specifici agli autori delle policy dei fornitori. È garantito che i tipi/attributi pubblici della piattaforma vengano mantenuti come API stabili per una determinata versione della piattaforma. La compatibilità con i tipi/attributi pubblici della piattaforma precedente può essere garantita per diverse versioni utilizzando i file di mappatura della piattaforma.

Sicurezza pubblica della piattaforma

La sepolicy pubblica della piattaforma include tutto ciò che è definito in system/sepolicy/public . La piattaforma può presupporre che i tipi e gli attributi definiti nelle norme pubbliche siano API stabili per una determinata versione della piattaforma. Ciò costituisce la parte della sepolicy esportata dalla piattaforma sulla quale gli sviluppatori di policy del fornitore (ovvero del dispositivo) possono scrivere ulteriori policy specifiche del dispositivo.

La versione dei tipi viene definita in base alla versione della policy rispetto alla quale vengono scritti i file del fornitore, definita dalla variabile di build PLATFORM_SEPOLICY_VERSION . La policy pubblica con versione viene quindi inclusa nella policy del fornitore e (nella sua forma originale) nella policy della piattaforma. Pertanto, la policy finale include la policy della piattaforma privata, la sepolicy pubblica della piattaforma corrente, la policy specifica del dispositivo e la policy pubblica con versione corrispondente alla versione della piattaforma rispetto alla quale è stata scritta la policy del dispositivo.

Sepolicy privata della piattaforma

La sepolicy privata della piattaforma include tutto ciò che è definito in /system/sepolicy/private . Questa parte della policy definisce i tipi, le autorizzazioni e gli attributi solo della piattaforma richiesti per la funzionalità della piattaforma. Questi non vengono esportati agli autori delle policy vendor/device . Gli autori di policy non di piattaforma non devono scrivere le proprie estensioni di policy in base a tipi/attributi/regole definiti nella sepolicy privata della piattaforma. Inoltre, queste regole possono essere modificate o possono scomparire come parte di un aggiornamento esclusivo del framework.

Mappatura privata della piattaforma

La mappatura privata della piattaforma include istruzioni di policy che associano gli attributi esposti nella policy pubblica della piattaforma delle versioni precedenti della piattaforma ai tipi concreti utilizzati nella sepolicy pubblica della piattaforma corrente. Ciò garantisce che la policy del fornitore scritta in base agli attributi pubblici della piattaforma delle versioni precedenti della sepolicy pubblica della piattaforma continui a funzionare. Il controllo delle versioni si basa sulla variabile di build PLATFORM_SEPOLICY_VERSION impostata in AOSP per una determinata versione della piattaforma. Esiste un file di mappatura separato per ciascuna versione precedente della piattaforma da cui si prevede che questa piattaforma accetti la politica del fornitore. Per ulteriori dettagli, vedere Compatibilità .

Android 11 e versioni successive

system_ext e sepolicy del prodotto

In Android 11 vengono aggiunte la policy system_ext e la policy del prodotto. Come la sepolicy della piattaforma, la policy system_ext e la policy del prodotto sono suddivise in policy pubblica e policy privata.

La politica pubblica viene esportata al fornitore. Tipi e attributi diventano API stabili e la politica del fornitore può fare riferimento a tipi e attributi nella politica pubblica. La versione dei tipi viene definita in base a PLATFORM_SEPOLICY_VERSION e la policy con versione è inclusa nella policy del fornitore. La policy originale è inclusa in ciascuna partizione system_ext e prodotto.

La policy privata contiene tipi, autorizzazioni e attributi solo system_ext e solo prodotto richiesti per la funzionalità system_ext e le partizioni del prodotto. La politica privata è invisibile al fornitore, il che implica che queste regole sono interne e possono essere modificate.

system_ext e mappatura del prodotto

system_ext e product possono esportare i tipi pubblici designati al fornitore. Tuttavia, la responsabilità di mantenere la compatibilità spetta a ciascun partner. Per compatibilità, i partner possono fornire i propri file di mappatura che mappano gli attributi con versione delle versioni precedenti ai tipi concreti utilizzati nell'attuale sepolicy pubblica.

  • Per installare un file di mappatura per system_ext, inserire un file cil contenente le informazioni di mappatura desiderate in {SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil , quindi aggiungere system_ext_{ver}.cil a PRODUCT_PACKAGES .
  • Per installare un file di mappatura per il prodotto, inserire un file cil contenente le informazioni di mappatura desiderate in {PRODUCT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil , quindi aggiungere product_{ver}.cil a PRODUCT_PACKAGES .
  • Fai riferimento a un esempio che aggiunge un file di mappatura della partizione del prodotto del dispositivo Redbull.

    Costruire la politica SELinux

    La policy SELinux in Android 8.0 viene creata combinando parti di /system e /vendor . La logica per configurarlo in modo appropriato è in /platform/system/sepolicy/Android.mk .

    La policy esiste nelle seguenti posizioni:

    Posizione Contiene
    system/sepolicy/public L'API sepolicy della piattaforma
    system/sepolicy/private Dettagli di implementazione della piattaforma (i fornitori possono ignorarli)
    system/sepolicy/vendor File di policy e contesto che i fornitori possono utilizzare (i fornitori possono ignorarli se lo desiderano)
    BOARD_SEPOLICY_DIRS Politica di riservatezza del fornitore
    BOARD_ODM_SEPOLICY_DIRS (Android 9 e versioni successive) Odm sepolicy
    SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 e versioni successive) API sepolicy di System_ext
    SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 e versioni successive) Dettagli di implementazione System_ext (i fornitori possono ignorarli)
    PRODUCT_PUBLIC_SEPOLICY_DIRS (Android 11 e versioni successive) API sepolicy del prodotto
    PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 e versioni successive) Dettagli di implementazione del prodotto (i fornitori possono ignorarli)

    Il sistema di compilazione accetta questa policy e produce i componenti system, system_ext, product, seller e odm policy sulla partizione corrispondente. I passaggi includono:

    1. Conversione delle policy nel formato SELinux Common Intermediate Language (CIL), in particolare:
      1. politica della piattaforma pubblica (sistema + system_ext + prodotto)
      2. politica combinata privata + pubblica
      3. public + fornitore e policy BOARD_SEPOLICY_DIRS
    2. Versionare la policy fornita dal pubblico come parte della policy del fornitore. Fatto utilizzando la policy CIL pubblica prodotta per informare la policy combinata pubblica + fornitore + BOARD_SEPOLICY_DIRS su quali parti devono essere trasformate in attributi che saranno collegati alla policy della piattaforma.
    3. Creazione di un file di mappatura che collega la piattaforma e le parti del fornitore. Inizialmente, questo collega semplicemente i tipi della politica pubblica con gli attributi corrispondenti nella politica del fornitore; successivamente fornirà anche la base per il file mantenuto nelle future versioni della piattaforma, consentendo la compatibilità con la politica del fornitore mirata a questa versione della piattaforma.
    4. Combinazione di file di policy (descrivere sia le soluzioni sul dispositivo che quelle precompilate).
      1. Combina mappatura, piattaforma e politica del fornitore.
      2. Compilare il file dei criteri binari di output.

    Politica SELinux precompilata

    Prima che init attivi SELinux, init raccoglie tutti i file CIL dalle partizioni ( system , system_ext , product , vendor e odm ) e li compila nella policy binaria, il formato che può essere caricato nel kernel. Poiché la compilazione richiede tempo (solitamente 1-2 secondi), i file CIL vengono precompilati al momento della compilazione e posizionati in /vendor/etc/selinux/precompiled_sepolicy o /odm/etc/selinux/precompiled_sepolicy , insieme agli hash sha256 dei file CIL di input. In fase di esecuzione, init controlla se qualcuno dei file di policy è stato aggiornato confrontando gli hash. Se non è cambiato nulla, init carica la policy precompilata. In caso contrario, init si compila al volo e lo usa al posto di quello precompilato.

    Più specificamente, la policy precompilata viene utilizzata se vengono soddisfatte tutte le seguenti condizioni. Qui, {partition} rappresenta la partizione in cui esiste la policy precompilata: vendor o odm .

    • Sia /system/etc/selinux/plat_sepolicy_and_mapping.sha256 che /{partition}/etc/selinux/precompiled_sepolicy.plat_sepolicy_and_mapping.sha256 esistono e sono identici.
    • Sia /system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256 che /{partition}/etc/selinux/precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256 non esistono. Oppure esistono entrambi e sono identici.
    • Sia /product/etc/selinux/product_sepolicy_and_mapping.sha256 che /{partition}/etc/selinux/precompiled_sepolicy.product_sepolicy_and_mapping.sha256 non esistono. Oppure esistono entrambi e sono identici.

    Se qualcuno di essi differisce, init ritorna al percorso di compilazione sul dispositivo. Vedi system/core/init/selinux.cpp per maggiori dettagli.