Crea il criterio SELinux

Questa pagina spiega 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 sono create separatamente. I fornitori di sistemi operativi 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 norme SELinux modulari sono archiviati nelle partizioni /vendor, il processo init deve montare le partizioni di sistema e del fornitore in precedenza per poter leggere i file SELinux da queste partizioni e unirli ai file SELinux principali nella directory di sistema (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 dei criteri SELinux di base di Android, inclusi contesti e file di criteri. Anche la logica principale di compilazione di sepolicy si trova qui (system/sepolicy/Android.mk).

Per maggiori dettagli sui file in system/sepolicy Implementazione di SELinux.

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. La policy combinata viene quindi passata al compilatore di policy 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 compilazione 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:

Questa immagine mostra la logica di compilazione di 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 quest'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.
    Questa immagine mostra i file che generano il file delle norme 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 norme (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 Implementazione di SELinux.

Inizializzazione di SELinux

All'avvio del sistema, SELinux è in modalità permissiva (e non in modalità applicazione). 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/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.mk.

Le norme esistono 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 norme e contesto che i fornitori possono utilizzare (i fornitori possono ignorarli, se vogliono)
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 sepolicy di system_ext
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 e versioni successive) Dettagli di implementazione di 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 prende queste norme e produce i componenti delle norme di sistema, system_ext, prodotto, fornitore e odm nella partizione corrispondente. I passaggi includono:

  1. Conversione delle norme nel formato SELinux Common Intermediate Language (CIL), in particolare:
    1. norme della piattaforma pubblica (sistema + system_ext + prodotto)
    2. norme combinate private e pubbliche
    3. public + vendor and BOARD_SEPOLICY_DIRS policy
  2. Controllo delle versioni delle norme fornite dal pubblico nell'ambito delle norme del fornitore. Questa operazione viene eseguita utilizzando le norme CIL pubbliche prodotte per informare le norme combinate pubbliche + fornitore + BOARD_SEPOLICY_DIRS su quali parti devono essere trasformate in attributi che verranno collegati alle norme della piattaforma.
  3. Creazione di un file di mapping che colleghi le parti della piattaforma e del fornitore. Inizialmente, questo collega solo i tipi delle norme pubbliche con gli attributi corrispondenti nelle norme del fornitore; in seguito fornirà anche la base per il file mantenuto nelle versioni future della piattaforma, consentendo la compatibilità con le norme del fornitore che hanno come target questa versione della piattaforma.
  4. Combinazione di file di policy (descrivi le soluzioni on-device e precompilate).
    1. Combina le norme relative a mapping, piattaforma e fornitori.
    2. Compila il file di criteri binari di output.

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 della norma 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 richiesti per la funzionalità della piattaforma. Questi non vengono esportati nei documenti delle norme di vendor/device. Gli autori di norme non di piattaforma non devono scrivere le estensioni delle norme in base a tipi/attributi/regole definiti nelle norme di sicurezza private 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à.

Android 11 e versioni successive

system_ext e product sepolicy

In Android 11 vengono aggiunti i criteri system_ext e product. Come la piattaforma sepolicy, le norme system_ext e le norme del prodotto 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 sono incluse nelle norme del fornitore. La policy originale è inclusa in ciascuna partizione system_ext e product.

L'informativa sulla privacy contiene tipi, autorizzazioni e attributi solo per system_ext e solo per il prodotto richiesti per la funzionalità delle partizioni system_ext e prodotto. 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 in vendor. Tuttavia, la responsabilità di mantenere la compatibilità è di ogni partner. 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 nella sepolicy pubblica attuale.

  • Per installare un file di mapping per system_ext, inserisci un file cil contenente le informazioni di mapping 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 mapping per il prodotto, inserisci un file cil contenente le informazioni di mapping 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 prodotto del dispositivo Redbull.

Policy SELinux precompilata

Prima che init attivi SELinux, 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.init Poiché la compilazione richiede tempo (di solito 1-2 secondi), i file CIL vengono precompilati al momento della creazione 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 controlla se uno dei file delle norme è stato aggiornato confrontando gli hash. Se non è cambiato nulla, init carica le norme precompilate. In caso contrario, init compila al volo e lo utilizza al posto di quello precompilato.

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 qualsiasi di questi valori è diverso, init torna al percorso di compilazione sul dispositivo. Per maggiori dettagli, consulta system/core/init/selinux.cpp.