Crea il criterio SELinux

Questa pagina descrive come viene creata la policy SELinux. Le norme SELinux sono create dalla combinazione delle norme AOSP di base (piattaforma) e delle norme specifiche del dispositivo (fornitore). Il flusso di build delle norme SELinux per Android 4.4 fino ad Android 7.0 univa tutti i frammenti sepolicy e generava file monolitici nella directory radice. Ciò significava che i fornitori di SoC e i produttori ODM modificavano boot.img (per i dispositivi non A/B) o system.img (per i dispositivi A/B) ogni volta che i criteri venivano modificati.

In Android 8.0 e versioni successive, le norme della piattaforma e del fornitore vengono create separatamente. I SoC e gli OEM possono aggiornare le proprie parti delle norme, creare le proprie immagini (ad esempio vendor.img e boot.img), quindi aggiornarle indipendentemente dagli aggiornamenti della piattaforma.

Tuttavia, poiché i file delle policy SELinux modulari sono archiviati nelle partizioni /vendor, il processo init deve montare le partizioni system e vendor in precedenza per poter leggere i file SELinux da queste partizioni e unirli ai file SELinux principali nella directory system (prima di caricarli nel kernel).

File di origine

La logica per la creazione di SELinux si trova in questi file:

  • external/selinux: Progetto SELinux esterno, utilizzato per creare utilità della riga di comando HOST per compilare policy ed etichette SELinux.
  • system/sepolicy: configurazioni principali delle norme SELinux di Android, inclusi contesti e file di norme. Anche la logica principale di compilazione di sepolicy si trova qui (system/sepolicy/Android.mk).

Per ulteriori dettagli sui file in system/sepolicy, vedi File delle chiavi.

Android 7.x e versioni precedenti

Questa sezione descrive come vengono create le norme SELinux in Android 7.x e versioni precedenti.

Procedura di compilazione per Android 7.x e versioni precedenti

La policy SELinux viene creata combinando la policy AOSP di base con le personalizzazioni specifiche del dispositivo. Le norme combinate vengono quindi trasmesse al compilatore delle norme e a vari controlli. La personalizzazione specifica per il dispositivo viene eseguita tramite la variabile BOARD_SEPOLICY_DIRS definita nel file Boardconfig.mk specifico per il dispositivo. Questa variabile di build globale contiene un elenco di directory che specificano l'ordine in cui cercare file di criteri 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

I contenuti dei file file_contexts in system/sepolicy e BOARD_SEPOLICY_DIRS vengono concatenati per generare file_contexts.bin sul dispositivo:

Logica di build SELinux per Android 7.x

Figura 1. Logica di compilazione di SELinux.

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

  • Il testo normale policy.conf viene generato concatenando i file security_classes, initial_sids, *.te, genfs_contexts e port_contexts in questo ordine.
  • Per ogni file (ad esempio security_classes), il contenuto è la concatenazione dei file con lo stesso nome in system/sepolicy/ e BOARDS_SEPOLICY_DIRS.
  • policy.conf viene inviato al compilatore SELinux per il controllo della sintassi e compilato in formato binario come sepolicy sul dispositivo.

    File che generano il file dei criteri SELinux
      per Android 7.x
    Figura 2. File di criteri SELinux.

File SELinux

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

  • selinux_version
  • sepolicy: Output binario dopo la combinazione dei file delle policy (ad esempio security_classes, initial_sids e *.te)
  • file_contexts
  • property_contexts
  • seapp_contexts
  • service_contexts
  • system/etc/mac_permissions.xml

Per maggiori dettagli, vedi Implementare SELinux.

Inizializzazione di SELinux

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

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

Per ridurre i tempi di avvio, esegui re-exec() sul processo init il prima possibile.

Android 8.0 e versioni successive

In Android 8.0, le norme SELinux sono suddivise in componenti della piattaforma e del fornitore per consentire aggiornamenti indipendenti delle norme della piattaforma e del fornitore, mantenendo la compatibilità.

La sepolicy della piattaforma è ulteriormente suddivisa in parti private e pubbliche per esportare tipi e attributi specifici per gli autori delle norme del fornitore. È 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 precedenti può essere garantita per diverse versioni utilizzando i file di mapping della piattaforma.

Processo di compilazione per Android 8.0

Il criterio SELinux in Android 8.0 è creato combinando parti di /system e /vendor. La logica per configurare correttamente questa impostazione si trova in /platform/system/sepolicy/Android.bp.

Le norme sono disponibili nelle seguenti posizioni:

Posizione Contiene
system/sepolicy/public API sepolicy della piattaforma
system/sepolicy/private Dettagli di implementazione della piattaforma (i fornitori possono ignorarli)
system/sepolicy/vendor File di criteri e contesto che i fornitori possono utilizzare (i fornitori possono ignorarli)
BOARD_SEPOLICY_DIRS Vendor sepolicy
BOARD_ODM_SEPOLICY_DIRS (Android 9 e versioni successive) ODM sepolicy
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 e versioni successive) API system_ext sepolicy
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 e versioni successive) system_ext Dettagli di implementazione (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 build prende questa policy e produce i componenti delle policy system, system_ext, product, vendor e odm nella partizione corrispondente. I passaggi includono:

  1. Converti le policy nel formato SELinux Common Intermediate Language (CIL), in particolare:
    • Norme della piattaforma pubblica (system, system_ext, product)
    • Norme private e pubbliche combinate
    • Norme relative a pubblico, fornitori e BOARD_SEPOLICY_DIRS
  2. Versiona le norme fornite dal pubblico nell'ambito delle norme del fornitore. Utilizza le norme CIL pubbliche prodotte per informare le norme combinate pubbliche e del fornitore e BOARD_SEPOLICY_DIRS su quali parti devono essere trasformate in attributi collegati alle norme della piattaforma.
  3. Crea un file di mapping che colleghi le parti della piattaforma e del fornitore. Inizialmente, questo collega solo i tipi della norma pubblica con gli attributi corrispondenti nella norma del fornitore; in seguito fornisce anche la base per il file mantenuto nelle versioni future della piattaforma, consentendo la compatibilità con il targeting della norma del fornitore di questa versione della piattaforma.
  4. Combina i file delle policy (descrivi le soluzioni on-device e precompilate).
    1. Combina le norme relative a mapping, piattaforma e fornitori.
    2. Compila il file binario di output dei criteri.

Platform public sepolicy

Il file sepolicy pubblico della piattaforma include tutto ciò che è definito in system/sepolicy/public. La piattaforma può presupporre che i tipi e gli attributi definiti nei criteri pubblici siano API stabili per una determinata versione della piattaforma. Questa parte di sepolicy viene esportata dalla piattaforma su cui gli sviluppatori di norme del fornitore (ovvero del dispositivo) possono scrivere norme aggiuntive specifiche per il dispositivo.

I tipi sono versionati in base alla versione del criterio rispetto alla quale vengono scritti i file del fornitore, definita dalla variabile di build PLATFORM_SEPOLICY_VERSION. La norma pubblica con controllo delle versioni viene quindi inclusa nella norma del fornitore e (nella sua forma originale) nella norma della piattaforma. Pertanto, le norme finali includono le norme della piattaforma privata, le norme di sicurezza pubbliche della piattaforma attuale, le norme specifiche del dispositivo e le norme pubbliche con controllo delle versioni corrispondenti alla versione della piattaforma in base alla quale sono state scritte le norme del dispositivo.

Platform private sepolicy

Le norme di sicurezza privata della piattaforma includono tutto ciò che è definito in /system/sepolicy/private. Questa parte delle norme costituisce tipi, autorizzazioni e attributi solo per la piattaforma necessari per la funzionalità della piattaforma. Questi non vengono esportati nei writer di criteri per fornitori e dispositivi. Gli autori di policy non di piattaforma non devono scrivere le estensioni delle loro policy in base a tipi, attributi e regole definiti nella sepolicy privata della piattaforma. Inoltre, queste regole possono essere modificate o potrebbero scomparire nell'ambito di un aggiornamento solo del framework.

Mapping privato della piattaforma

Il mapping privato della piattaforma include dichiarazioni delle norme che mappano gli attributi esposti nelle norme pubbliche della piattaforma delle versioni precedenti della piattaforma ai tipi concreti utilizzati nelle norme di sicurezza pubbliche della piattaforma attuali. In questo modo, la policy del fornitore scritta in base agli attributi pubblici della piattaforma delle versioni precedenti di sepolicy pubbliche della piattaforma continua 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 mapping separato per ogni versione precedente della piattaforma da cui è previsto che questa piattaforma accetti le norme del fornitore. Per maggiori dettagli, vedi Compatibilità delle policy.

Android 11 e versioni successive

Questa sezione descrive come viene creata la policy SELinux in Android 11 e versioni successive.

system_ext e sepolicy del prodotto

In Android 11 vengono aggiunti i criteri system_ext e product. Come le norme sepolicy della piattaforma, le norme system_ext e le norme product sono suddivise in norme pubbliche e norme private.

Le norme pubbliche vengono esportate al fornitore. I tipi e gli attributi diventano API stabili e le norme del fornitore possono fare riferimento a tipi e attributi nelle norme pubbliche. I tipi vengono versionati in base a PLATFORM_SEPOLICY_VERSION e le norme versionate vengono incluse nelle norme del fornitore. Il criterio originale è incluso in ciascuna partizione system_ext e product.

La norma sulla privacy contiene tipi, autorizzazioni e attributi solo system_ext e solo product richiesti per la funzionalità di partizione system_ext e product. Le norme private non sono visibili al fornitore, il che implica che queste regole sono interne e possono essere modificate.

system_ext and product mapping

system_ext e product possono esportare i tipi pubblici designati al fornitore. Tuttavia, ogni partner ha la responsabilità di mantenere la compatibilità. Per la compatibilità, i partner possono fornire i propri file di mapping che mappano gli attributi con controllo delle versioni delle versioni precedenti ai tipi concreti utilizzati nelle sepolicy pubbliche attuali:

  • Per installare un file di mappatura per system_ext, inserisci un file CIL contenente le informazioni di mappatura desiderate in {SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil, quindi aggiungi system_ext_{ver}.cil a PRODUCT_PACKAGES.
  • Per installare un file di mappatura per product, inserisci un file CIL contenente le informazioni di mappatura desiderate in {PRODUCT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil, quindi aggiungi product_{ver}.cil a PRODUCT_PACKAGES.

Fai riferimento a un esempio che aggiunge un file di mappatura della partizione product di un dispositivo Redbull.

Policy 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 in una policy binaria, il formato che può essere caricato nel kernel. Poiché la compilazione richiede tempo (di solito 1-2 secondi), i file CIL vengono precompilati in fase di compilazione e inseriti in /vendor/etc/selinux/precompiled_sepolicy o /odm/etc/selinux/precompiled_sepolicy, insieme agli hash sha256 dei file CIL di input. In fase di runtime, init verifica se uno dei file delle norme è stato aggiornato confrontando gli hash. Se non è cambiato nulla, init carica le norme precompilate. In caso contrario, init esegue la compilazione al volo e la utilizza al posto di quella precompilata.

Più nello specifico, la norma precompilata viene utilizzata se sono soddisfatte tutte le seguenti condizioni. Qui, {partition} rappresenta la partizione in cui esiste la norma precompilata: vendor o odm.

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

Se uno di questi è diverso, init torna al percorso di compilazione sul dispositivo. Per maggiori dettagli, consulta system/core/init/selinux.cpp.