Compatibilità delle politiche

Questo articolo descrive come Android gestisce i problemi di compatibilità delle policy con le OTA della piattaforma, in cui le impostazioni SELinux della nuova piattaforma potrebbero differire dalle impostazioni SELinux del vecchio fornitore.

La progettazione della politica SELinux basata su Treble considera una distinzione binaria tra politica della piattaforma e politica del fornitore ; lo schema diventa più complicato se le partizioni del fornitore generano dipendenze, come platform < vendor < oem .

In Android 8.0 e versioni successive, la policy globale di SELinux è divisa in componenti privati ​​e pubblici. I componenti pubblici sono costituiti dalla policy e dall'infrastruttura associata, la cui disponibilità è garantita per una versione della piattaforma. Questa policy verrà esposta agli autori delle policy del fornitore per consentire ai fornitori di creare un file di policy del fornitore che, se combinato con la policy fornita dalla piattaforma, si traduce in una policy completamente funzionale per un dispositivo.

  • Per il controllo delle versioni, la politica pubblica della piattaforma esportata verrà scritta come attributi .
  • Per facilitare la scrittura della policy, i tipi esportati verranno trasformati in attributi con versione come parte del processo di creazione della policy. I tipi pubblici possono anche essere utilizzati direttamente nelle decisioni di etichettatura fornite dai file di contesto del fornitore.

Android mantiene una mappatura tra i tipi concreti esportati nella policy della piattaforma e gli attributi con versione corrispondenti per ciascuna versione della piattaforma . Ciò garantisce che quando gli oggetti vengono etichettati con un tipo, ciò non interrompe il comportamento garantito dalla politica pubblica della piattaforma in una versione precedente. Questa mappatura viene mantenuta mantenendo aggiornato un file di mappatura per ciascuna versione della piattaforma , che conserva le informazioni sull'appartenenza agli attributi per ciascun tipo esportato nella politica pubblica.

Proprietà degli oggetti ed etichettatura

Quando si personalizzano i criteri in Android 8.0 e versioni successive, la proprietà deve essere definita chiaramente per ciascun oggetto per mantenere separati i criteri della piattaforma e del fornitore. Ad esempio, se il fornitore etichetta /dev/foo e la piattaforma etichetta poi /dev/foo in una OTA successiva, si verificherà un comportamento indefinito. Per SELinux, questo si manifesta come una collisione di etichette. Il nodo del dispositivo può avere solo una singola etichetta che si risolve in quella applicata per ultima. Di conseguenza:

  • I processi che necessitano di accedere all'etichetta applicata senza successo perderanno l'accesso alla risorsa.
  • I processi che ottengono l'accesso al file potrebbero interrompersi perché è stato creato il nodo del dispositivo sbagliato.

Le proprietà del sistema hanno anche il potenziale per nominare le collisioni che potrebbero risultare in un comportamento indefinito sul sistema (così come per l'etichettatura di SELinux). Possono verificarsi conflitti tra le etichette della piattaforma e del fornitore per qualsiasi oggetto che abbia un'etichetta SELinux, incluse proprietà, servizi, processi, file e socket. Per evitare questi problemi, definire chiaramente la proprietà di questi oggetti.

Oltre alle collisioni di etichette, anche i nomi di tipi/attributi di SELinux potrebbero entrare in collisione. Una collisione tra nomi di tipo/attributo comporterà sempre un errore del compilatore di policy.

Spazio dei nomi tipo/attributo

SELinux non consente dichiarazioni multiple dello stesso tipo/attributo. La policy con dichiarazioni duplicate non verrà compilata. Per evitare conflitti tra tipi e nomi di attributi, tutte le dichiarazioni del fornitore dovrebbero avere spazi dei nomi che iniziano con np_ .

type foo, domain; → type np_foo, domain;

Proprietà del sistema e proprietà dell'etichettatura del processo

Il modo migliore per evitare collisioni di etichettatura è utilizzare gli spazi dei nomi delle proprietà. Per identificare facilmente le proprietà della piattaforma ed evitare conflitti di nomi durante la ridenominazione o l'aggiunta di proprietà della piattaforma esportata, assicurati che tutte le proprietà del fornitore abbiano i propri prefissi:

Tipo di proprietà Prefissi accettabili
proprietà di controllo ctl.vendor.
ctl.start$vendor.
ctl.stop$vendor.
init.svc.vendor.
leggibile-scrivibile vendor.
sola lettura ro.vendor.
ro.boot.
ro.hardware.
persistente persist.vendor.

I fornitori possono continuare a utilizzare ro.boot.* (che proviene dalla riga cmd del kernel) e ro.hardware.* (un'ovvia proprietà correlata all'hardware).

Tutti i servizi del fornitore nei file init rc dovrebbero avere vendor. per i servizi nei file init rc di partizioni non di sistema. Regole simili vengono applicate alle etichette SELinux per le proprietà del fornitore ( vendor_ per le proprietà del fornitore).

Proprietà del file

Prevenire le collisioni per i file è impegnativo perché la piattaforma e la politica del fornitore forniscono comunemente etichette per tutti i filesystem. A differenza della denominazione dei tipi, lo spazio dei nomi dei file non è pratico poiché molti di essi vengono creati dal kernel. Per evitare queste collisioni, seguire le indicazioni per la denominazione dei file system in questa sezione. Per Android 8.0, si tratta di raccomandazioni senza applicazione tecnica. In futuro, queste raccomandazioni verranno applicate dalla Vendor Test Suite (VTS).

Sistema (/sistema)

Solo l'immagine di sistema deve fornire etichette per i componenti /system tramite file_contexts , service_contexts e così via. Se le etichette per i componenti /system vengono aggiunte nella policy /vendor , un aggiornamento OTA solo del framework potrebbe non essere possibile.

Venditore (/venditore)

La policy AOSP SELinux etichetta già parti della partizione vendor con cui interagisce la piattaforma, il che consente di scrivere regole SELinux per i processi della piattaforma per poter comunicare e/o accedere a parti della partizione vendor . Esempi:

/vendor Etichetta fornita dalla piattaforma Processi della piattaforma in base all'etichetta
/vendor(/. * )? vendor_file Tutti i client HAL in framework, ueventd , ecc.
/vendor/framework(/. * )? vendor_framework_file dex2oat , appdomain , ecc.
/vendor/app(/. * )? vendor_app_file dex2oat , installd , idmap , ecc.
/vendor/overlay(/. * ) vendor_overlay_file system_server , zygote , idmap , ecc.

Di conseguenza, è necessario seguire regole specifiche (applicate tramite neverallows ) quando si etichettano file aggiuntivi nella partizione vendor :

  • vendor_file deve essere l'etichetta predefinita per tutti i file nella partizione vendor . La policy della piattaforma lo richiede per accedere alle implementazioni HAL passthrough.
  • Tutti i nuovi exec_types aggiunti nella partizione vendor tramite SEPolicy del fornitore devono avere l'attributo vendor_file_type . Ciò viene applicato tramite neverallows.
  • Per evitare conflitti con futuri aggiornamenti della piattaforma/framework, evitare di etichettare file diversi da exec_types nella partizione vendor .
  • Tutte le dipendenze della libreria per gli HAL dello stesso processo identificati da AOSP devono essere etichettati come same_process_hal_file.

Procf (/proc)

I file in /proc possono essere etichettati utilizzando solo l'etichetta genfscon . In Android 7.0, sia la piattaforma che la policy del fornitore utilizzavano genfscon per etichettare i file in procfs .

Raccomandazione: solo le etichette dei criteri della piattaforma /proc . Se i processi vendor necessitano di accedere ai file in /proc che sono attualmente etichettati con l'etichetta predefinita ( proc ), la politica del fornitore non dovrebbe etichettarli esplicitamente e dovrebbe invece utilizzare il tipo proc generico per aggiungere regole per i domini del fornitore. Ciò consente agli aggiornamenti della piattaforma di adattarsi alle future interfacce del kernel esposte tramite procfs e di etichettarle esplicitamente secondo necessità.

Debugf (/sys/kernel/debug)

Debugfs può essere etichettato sia in file_contexts che genfscon . Da Android 7.0 ad Android 10, sia la piattaforma che l'etichetta del fornitore debugfs .

In Android 11 non è possibile accedere o montare debugfs sui dispositivi di produzione. I produttori di dispositivi dovrebbero rimuovere debugfs .

Tracef (/sys/kernel/debug/tracing)

Tracefs possono essere etichettati sia in file_contexts che genfscon . In Android 7.0, solo la piattaforma etichetta tracefs .

Raccomandazione: solo la piattaforma può etichettare tracefs .

Sysfs (/sys)

I file in /sys possono essere etichettati utilizzando sia file_contexts che genfscon . In Android 7.0, sia la piattaforma che il fornitore utilizzano file_contexts e genfscon per etichettare i file in sysfs .

Raccomandazione: la piattaforma può etichettare i nodi sysfs che non sono specifici del dispositivo. Altrimenti, solo il fornitore potrà etichettare i file.

tmpfs (/dev)

I file in /dev possono essere etichettati in file_contexts . In Android 7.0, sia la piattaforma che l'etichetta del fornitore vengono file qui.

Raccomandazione: il fornitore può etichettare solo i file in /dev/vendor (ad esempio, /dev/vendor/foo , /dev/vendor/socket/bar ).

Rootf (/)

I file in / possono essere etichettati in file_contexts . In Android 7.0, sia la piattaforma che l'etichetta del fornitore vengono file qui.

Raccomandazione: solo il sistema può etichettare i file in / .

Dati (/dati)

I dati vengono etichettati tramite una combinazione di file_contexts e seapp_contexts .

Raccomandazione: non consentire l'etichettatura del fornitore all'esterno /data/vendor . Solo la piattaforma può etichettare altre parti di /data .

Attributi di compatibilità

La policy SELinux è un'interazione tra tipi di origine e di destinazione per classi di oggetti e autorizzazioni specifiche. Ogni oggetto (processi, file, ecc.) interessato dalla politica SELinux può avere un solo tipo, ma quel tipo può avere più attributi.

La policy è scritta principalmente in termini di tipologie esistenti:

allow source_type target_type:target_class permission(s);

Funziona perché la politica è stata scritta con conoscenze di tutti i tipi. Tuttavia, se la policy del fornitore e la policy della piattaforma utilizzano tipi specifici e l'etichetta di un oggetto specifico cambia solo in una di tali policy, l'altra potrebbe contenere policy che hanno ottenuto o perso l'accesso su cui si faceva affidamento in precedenza. Per esempio:

File_contexts:
/sys/A   u:object_r:sysfs:s0
Platform: allow p_domain sysfs:class perm;
Vendor: allow v_domain sysfs:class perm;

Potrebbe essere cambiato in:

File_contexts:
/sys/A   u:object_r:sysfs_A:s0

Anche se la politica del fornitore rimarrebbe la stessa, il v_domain perderebbe l'accesso a causa della mancanza di politica per il nuovo tipo sysfs_A .

Definendo una policy in termini di attributi, possiamo dare all'oggetto sottostante un tipo che ha un attributo corrispondente alla policy sia per la piattaforma che per il codice del fornitore. Questo può essere fatto per tutti i tipi per creare in modo efficace una politica degli attributi in cui i tipi concreti non vengono mai utilizzati. In pratica, ciò è richiesto solo per le porzioni di policy che si sovrappongono tra piattaforma e fornitore, che sono definite e fornite come policy pubblica della piattaforma che viene costruita come parte della policy del fornitore.

La definizione delle politiche pubbliche come attributi con versione soddisfa due obiettivi di compatibilità delle politiche:

  • Assicurati che il codice del fornitore continui a funzionare dopo l'aggiornamento della piattaforma . Ottenuto aggiungendo attributi a tipi concreti per oggetti corrispondenti a quelli su cui si basava il codice del fornitore, preservando l'accesso.
  • Capacità di deprecare la politica . Ottenuto delineando chiaramente i set di policy in attributi che possono essere rimossi non appena la versione a cui corrispondono non è più supportata. Lo sviluppo può continuare nella piattaforma, sapendo che la vecchia politica è ancora presente nella politica del fornitore e verrà automaticamente rimossa quando/se verrà aggiornata.

Scrivibilità delle policy

Per raggiungere l'obiettivo di non richiedere la conoscenza di modifiche di versione specifiche per lo sviluppo delle policy, Android 8.0 include una mappatura tra i tipi di policy pubbliche della piattaforma e i relativi attributi. Il tipo foo è mappato sull'attributo foo_v N , dove N è la versione target. vN corrisponde alla variabile di build PLATFORM_SEPOLICY_VERSION ed è nel formato MM.NN , dove MM corrisponde al numero SDK della piattaforma e NN è una versione specifica della sepolicy della piattaforma.

Gli attributi nella politica pubblica non hanno una versione, ma esistono piuttosto come un'API su cui è possibile costruire la politica della piattaforma e del fornitore per mantenere stabile l'interfaccia tra le due partizioni. Sia gli autori delle policy della piattaforma che quelli dei fornitori possono continuare a scrivere la policy così come viene scritta oggi.

Politica pubblica della piattaforma esportata come allow source_foo target_bar: class perm ; è incluso come parte della politica del fornitore. In fase di compilazione (che comprende la versione corrispondente) viene trasformata nella policy che andrà alla porzione venditore del dispositivo (mostrata nel Common Intermediate Language (CIL) trasformato):

 (allow source_foo_vN target_bar_vN (class (perm)))

Poiché la politica del fornitore non è mai in anticipo rispetto alla piattaforma, non dovrebbe preoccuparsi delle versioni precedenti. Tuttavia, la politica della piattaforma dovrà sapere quanto è arretrata la politica del fornitore, includere attributi nei suoi tipi e impostare la politica corrispondente agli attributi con versione.

Differenze politiche

La creazione automatica degli attributi aggiungendo _v N alla fine di ogni tipo non fa nulla senza la mappatura degli attributi ai tipi attraverso le differenze di versione. Android mantiene una mappatura tra le versioni per gli attributi e una mappatura dei tipi su tali attributi. Questo viene fatto nei suddetti file di mappatura con istruzioni come (CIL):

(typeattributeset foo_vN (foo))

Aggiornamenti della piattaforma

La sezione seguente descrive in dettaglio gli scenari per gli aggiornamenti della piattaforma.

Stessi tipi

Questo scenario si verifica quando un oggetto non modifica le etichette nelle versioni dei criteri. Questo è lo stesso per i tipi di origine e di destinazione e può essere visto con /dev/binder , che è etichettato binder_device in tutte le versioni. Nella politica trasformata è rappresentato come:

binder_device_v1 … binder_device_vN

Quando si esegue l'aggiornamento da v1v2 , la policy della piattaforma deve contenere:

type binder_device; -> (type binder_device) (in CIL)

Nel file di mappatura v1 (CIL):

(typeattributeset binder_device_v1 (binder_device))

Nel file di mappatura v2 (CIL):

(typeattributeset binder_device_v2 (binder_device))

Nella politica del fornitore v1 (CIL):

(typeattribute binder_device_v1)
(allow binder_device_v1 …)

Nella politica del fornitore v2 (CIL):

(typeattribute binder_device_v2)
(allow binder_device_v2 …)
Nuovi tipi

Questo scenario si verifica quando alla piattaforma viene aggiunto un nuovo tipo, cosa che può verificarsi quando si aggiungono nuove funzionalità o durante il rafforzamento delle policy.

  • Nuova caratteristica . Quando il tipo etichetta un oggetto che precedentemente non esisteva (come un nuovo processo di servizio), il codice del fornitore non interagiva in precedenza con esso direttamente, quindi non esiste alcuna policy corrispondente. Il nuovo attributo corrispondente al tipo non ha un attributo nella versione precedente e quindi non avrebbe bisogno di una voce nel file di mappatura destinato a quella versione.
  • Inasprimento delle politiche . Quando il tipo rappresenta il rafforzamento della politica, il nuovo attributo di tipo deve ricollegarsi a una catena di attributi corrispondente a quella precedente (simile all'esempio precedente che cambia /sys/A da sysfs a sysfs_A ). Il codice del fornitore si basa su una regola che abilita l'accesso a sysfs e deve includere tale regola come attributo del nuovo tipo.

Quando si esegue l'aggiornamento da v1v2 , la policy della piattaforma deve contenere:

type sysfs_A; -> (type sysfs_A) (in CIL)
type sysfs; (type sysfs) (in CIL)

Nel file di mappatura v1 (CIL):

(typeattributeset sysfs_v1 (sysfs sysfs_A))

Nel file di mappatura v2 (CIL):

(typeattributeset sysfs_v2 (sysfs))
(typeattributeset sysfs_A_v2 (sysfs_A))

Nella politica del fornitore v1 (CIL):

(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

Nella politica del fornitore v2 (CIL):

(typeattribute sysfs_A_v2)
(allow … sysfs_A_v2 …)
(typeattribute sysfs_v2)
(allow … sysfs_v2 …)
Tipi rimossi

Questo (raro) scenario si verifica quando un tipo viene rimosso, cosa che può accadere quando l'oggetto sottostante:

  • Rimane ma ottiene un'etichetta diversa.
  • Viene rimosso dalla piattaforma.

Durante l'allentamento delle politiche, un tipo viene rimosso e all'oggetto etichettato con quel tipo viene assegnata un'etichetta diversa, già esistente. Ciò rappresenta una fusione delle mappature degli attributi: il codice del fornitore deve ancora essere in grado di accedere all'oggetto sottostante tramite l'attributo che possedeva prima, ma il resto del sistema deve ora essere in grado di accedervi con il suo nuovo attributo.

Se l'attributo a cui è stato cambiato è nuovo, la rietichettatura è la stessa del caso del nuovo tipo, tranne che quando viene utilizzata un'etichetta esistente, l'aggiunta del vecchio attributo nuovo tipo causerebbe anche altri oggetti etichettati con questo tipo essere nuovamente accessibile. Questo è essenzialmente ciò che viene fatto dalla piattaforma ed è considerato un compromesso accettabile per mantenere la compatibilità.

(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

Esempio Versione 1: compressione dei tipi (rimozione di sysfs_A)

Quando si esegue l'aggiornamento da v1v2 , la policy della piattaforma deve contenere:

type sysfs; (type sysfs) (in CIL)

Nel file di mappatura v1 (CIL):

(typeattributeset sysfs_v1 (sysfs))
(type sysfs_A) # in case vendors used the sysfs_A label on objects
(typeattributeset sysfs_A_v1 (sysfs sysfs_A))

Nel file di mappatura v2 (CIL):

(typeattributeset sysfs_v2 (sysfs))

Nella politica del fornitore v1 (CIL):

(typeattribute sysfs_A_v1)
(allow … sysfs_A_v1 …)
(typeattribute sysfs_v1)
(allow … sysfs_v1 …)

Nella politica del fornitore v2 (CIL):

(typeattribute sysfs_v2)
(allow … sysfs_v2 …)

Esempio Versione 2: rimozione completa (tipo foo)

Quando si esegue l'aggiornamento da v1v2 , la policy della piattaforma deve contenere:

# nothing - we got rid of the type

Nel file di mappatura v1 (CIL):

(type foo) #needed in case vendors used the foo label on objects
(typeattributeset foo_v1 (foo))

Nel file di mappatura v2 (CIL):

# nothing - get rid of it

Nella politica del fornitore v1 (CIL):

(typeattribute foo_v1)
(allow foo …)
(typeattribute sysfs_v1)
(allow sysfs_v1 …)

Nella politica del fornitore v2 (CIL):

(typeattribute sysfs_v2)
(allow sysfs_v2 …)
Nuova classe/permessi

Questo scenario si verifica quando un aggiornamento della piattaforma introduce nuovi componenti della policy che non esistono nelle versioni precedenti. Ad esempio, quando Android ha aggiunto il gestore oggetti servicemanager che ha creato le autorizzazioni di aggiunta, ricerca ed elenco, i daemon del fornitore che desideravano registrarsi con servicemanager necessitavano di autorizzazioni che non erano disponibili. In Android 8.0, solo i criteri della piattaforma possono aggiungere nuove classi e autorizzazioni.

Per consentire a tutti i domini che avrebbero potuto essere creati o estesi dalla policy del fornitore di utilizzare la nuova classe senza ostacoli, la policy della piattaforma deve includere una regola simile a:

allow {domain -coredomain} *:new_class perm;

Ciò potrebbe anche richiedere una politica che consenta l'accesso a tutti i tipi di interfaccia (politica pubblica), per essere sicuri che l'immagine del fornitore ottenga l'accesso. Se ciò si traduce in una politica di sicurezza inaccettabile (come potrebbe accadere con le modifiche del servicemanager), potrebbe essere forzato un aggiornamento del fornitore.

Classe/permessi rimossi

Questo scenario si verifica quando un gestore oggetti viene rimosso (come il gestore oggetti ZygoteConnection ) e non dovrebbe causare problemi. La classe del gestore oggetti e le autorizzazioni potrebbero rimanere definite nella policy finché la versione del fornitore non la utilizzerà più. Questo viene fatto aggiungendo le definizioni al file di mappatura corrispondente.

Personalizzazione del fornitore per tipi nuovi/rietichettati

I nuovi tipi di fornitori sono al centro dello sviluppo delle politiche dei fornitori poiché sono necessari per descrivere nuovi processi, file binari, dispositivi, sottosistemi e dati archiviati. Pertanto, è fondamentale consentire la creazione di tipi definiti dal fornitore.

Poiché la policy del fornitore è sempre la più vecchia sul dispositivo, non è necessario convertire automaticamente tutti i tipi di fornitore in attributi nella policy. La piattaforma non fa affidamento su nulla di etichettato nella politica del fornitore perché la piattaforma non ne è a conoscenza; tuttavia, la piattaforma fornirà gli attributi e i tipi pubblici che utilizza per interagire con gli oggetti etichettati con questi tipi (come domain , sysfs_type , ecc.). Affinché la piattaforma continui a interagire correttamente con questi oggetti, gli attributi e i tipi devono essere applicati in modo appropriato e potrebbe essere necessario aggiungere regole specifiche ai domini personalizzabili (come init ).

Modifiche agli attributi per Android 9

I dispositivi che vengono aggiornati ad Android 9 possono utilizzare i seguenti attributi, ma i dispositivi che vengono avviati con Android 9 non devono.

Attributi del violatore

Android 9 include questi attributi relativi al dominio:

  • data_between_core_and_vendor_violators . Attributo per tutti i domini che violano il requisito di non condividere file tramite percorso tra vendor e coredomains . I processi della piattaforma e del fornitore non devono utilizzare file su disco per comunicare (ABI instabile). Raccomandazione:
    • Il codice del fornitore deve utilizzare /data/vendor .
    • Il sistema non deve utilizzare /data/vendor .
  • system_executes_vendor_violators . Attributo per tutti i domini di sistema (eccetto i domini init e shell domains ) che violano il requisito di non eseguire i file binari del fornitore. L'esecuzione dei file binari del fornitore ha un'API instabile. La piattaforma non deve eseguire direttamente i file binari del fornitore. Raccomandazione:
    • Tali dipendenze della piattaforma dai file binari del fornitore devono essere alla base degli HAL HIDL.

      O

    • coredomains che necessitano di accesso ai file binari del fornitore dovrebbero essere spostati nella partizione del fornitore e quindi smettere di essere coredomain .

Attributi non attendibili

Le app non attendibili che ospitano codice arbitrario non dovrebbero avere accesso ai servizi HwBinder, ad eccezione di quelli considerati sufficientemente sicuri per l'accesso da tali app (vedere servizi sicuri di seguito). Le due ragioni principali sono:

  1. I server HwBinder non eseguono l'autenticazione client perché HIDL attualmente non espone le informazioni sull'UID del chiamante. Anche se HIDL esponesse tali dati, molti servizi HwBinder operano a un livello inferiore a quello delle app (come gli HAL) o non devono fare affidamento sull'identità dell'app per l'autorizzazione. Pertanto, per sicurezza, il presupposto predefinito è che ogni servizio HwBinder tratti tutti i suoi client come ugualmente autorizzati a eseguire le operazioni offerte dal servizio.
  2. I server HAL (un sottoinsieme dei servizi HwBinder) contengono codice con un tasso di incidenza di problemi di sicurezza più elevato rispetto ai componenti system/core e hanno accesso agli strati inferiori dello stack (fino all'hardware), aumentando così le opportunità di aggirare il modello di sicurezza Android .

Servizi sicuri

I servizi sicuri includono:

  • same_process_hwservice . Questi servizi (per definizione) vengono eseguiti nel processo del client e quindi hanno lo stesso accesso del dominio client in cui viene eseguito il processo.
  • coredomain_hwservice . Questi servizi non presentano rischi associati al motivo n. 2.
  • hal_configstore_ISurfaceFlingerConfigs . Questo servizio è specificamente progettato per l'utilizzo da parte di qualsiasi dominio.
  • hal_graphics_allocator_hwservice . Queste operazioni sono offerte anche dal servizio surfaceflinger Binder, al quale le app possono accedere.
  • hal_omx_hwservice . Questa è una versione HwBinder del servizio mediacodec Binder, a cui le app possono accedere.
  • hal_codec2_hwservice . Questa è una versione più recente di hal_omx_hwservice .

Attributi utilizzabili

Tutti hwservices non considerati sicuri hanno l'attributo untrusted_app_visible_hwservice . I server HAL corrispondenti hanno l'attributo untrusted_app_visible_halserver . I dispositivi avviati con Android 9 NON DEVONO utilizzare nessuno degli attributi untrusted .

Raccomandazione:

  • Le app non attendibili dovrebbero invece comunicare con un servizio di sistema che dialoga con il fornitore HIDL HAL. Ad esempio, le app possono parlare con binderservicedomain , quindi mediaserver (che è un binderservicedomain ) a sua volta parla con hal_graphics_allocator .

    O

  • Le app che necessitano dell'accesso diretto agli HAL vendor devono avere il proprio dominio sepolicy definito dal fornitore.

Test degli attributi di file

Android 9 include test in fase di compilazione che garantiscono che tutti i file in posizioni specifiche abbiano gli attributi appropriati (ad esempio, tutti i file in sysfs hanno l'attributo sysfs_type richiesto).

Politica pubblica-piattaforma

La policy piattaforma pubblica è il fulcro della conformità al modello di architettura Android 8.0 senza semplicemente mantenere l'unione delle policy della piattaforma v1 e v2. I fornitori sono esposti a un sottoinsieme della policy della piattaforma che contiene tipi e attributi utilizzabili e regole su tali tipi e attributi che poi diventano parte della policy del fornitore (ad esempio vendor_sepolicy.cil ).

I tipi e le regole vengono automaticamente tradotti nella policy generata dal fornitore in attribute_v N in modo tale che tutti i tipi forniti dalla piattaforma siano attributi con versione (tuttavia gli attributi non hanno versione). La piattaforma è responsabile della mappatura dei tipi concreti che fornisce negli attributi appropriati per garantire che la politica del fornitore continui a funzionare e che le regole fornite per una particolare versione siano incluse. La combinazione della politica della piattaforma pubblica e della politica del fornitore soddisfa l'obiettivo del modello di architettura Android 8.0 di consentire build di piattaforme e fornitori indipendenti.

Mappatura per catene di attributi

Quando si utilizzano gli attributi per mappare le versioni della policy, un tipo viene mappato a uno o più attributi, garantendo che gli oggetti etichettati con il tipo siano accessibili tramite attributi corrispondenti ai loro tipi precedenti.

Mantenere l'obiettivo di nascondere le informazioni sulla versione allo scrittore della policy significa generare automaticamente gli attributi con versione e assegnarli ai tipi appropriati. Nel caso comune dei tipi statici, questo è semplice: type_foo viene mappato a type_foo_v1 .

Per una modifica dell'etichetta di un oggetto come sysfssysfs_A o mediaserveraudioserver , la creazione di questa mappatura non è banale (ed è descritta negli esempi sopra). I manutentori delle policy della piattaforma devono determinare come creare la mappatura nei punti di transizione per gli oggetti, il che richiede la comprensione della relazione tra gli oggetti e le etichette assegnate e la determinazione di quando ciò si verifica. Per compatibilità con le versioni precedenti, questa complessità deve essere gestita dal lato della piattaforma, che è l'unica partizione che può aumentare il numero di giri.

Versione uprev

Per semplicità, la piattaforma Android rilascia una versione sepolicy quando viene tagliato un nuovo ramo di rilascio. Come descritto sopra, il numero di versione è contenuto in PLATFORM_SEPOLICY_VERSION ed è nel formato MM.nn , dove MM corrisponde al valore SDK e nn è un valore privato gestito in /platform/system/sepolicy. Ad esempio, 19.0 per Kitkat, 21.0 per Lollipop, 22.0 per Lollipop-MR1, 23.0 per Marshmallow, 24.0 per Nougat, 25.0 per Nougat-MR1, 26.0 per Oreo, 27.0 per Oreo-MR1 e 28.0 per Android 9. Gli uprev non sono sempre numeri interi. Ad esempio, se un bump MR a una versione richiede una modifica incompatibile in system/sepolicy/public ma non un bump API, la versione sepolicy potrebbe essere: vN.1 . La versione presente in un ramo di sviluppo è una 10000.0 dei dispositivi da non utilizzare mai nei dispositivi di spedizione.

Android potrebbe deprecare la versione più vecchia durante l'aggiornamento. Per informazioni su quando deprecare una versione, Android può raccogliere il numero di dispositivi con criteri del fornitore che eseguono quella versione di Android e che continuano a ricevere importanti aggiornamenti della piattaforma. Se il numero è inferiore a una determinata soglia, quella versione è deprecata.

Impatto sulle prestazioni di più attributi

Come descritto in https://github.com/SELinuxProject/cil/issues/9 , un gran numero di attributi assegnati a un tipo provocano problemi di prestazioni in caso di mancata cache delle policy.

È stato confermato che si tratta di un problema in Android, pertanto sono state apportate modifiche ad Android 8.0 per rimuovere gli attributi aggiunti alla policy dal compilatore della policy, nonché per rimuovere gli attributi inutilizzati. Queste modifiche hanno risolto le regressioni delle prestazioni.

Politica pubblica System_ext e politica pubblica del prodotto

A partire da Android 11, le partizioni system_ext e product possono esportare i tipi pubblici designati nella partizione del fornitore. Come la politica pubblica della piattaforma, il fornitore utilizza tipi e regole tradotti automaticamente negli attributi con versione, ad esempio da type a type_ N , dove N è la versione della piattaforma rispetto alla quale è creata la partizione del fornitore.

Quando le partizioni system_ext e product sono basate sulla stessa versione della piattaforma N , il sistema di compilazione genera file di mappatura di base su system_ext/etc/selinux/mapping/ N .cil e product/etc/selinux/mapping/ N .cil , che contengono identità mappature da type a type_ N . Il fornitore può accedere type con l'attributo con versione type_ N .

Nel caso in cui vengano aggiornate solo le partizioni system_ext e product, ad esempio N a N+1 (o successive), mentre il fornitore rimane su N , il fornitore potrebbe perdere l'accesso ai tipi delle partizioni system_ext e product. Per evitare interruzioni, le partizioni system_ext e product dovrebbero fornire file di mappatura dai tipi concreti agli attributi type_ N . Ciascun partner è responsabile della manutenzione dei file di mappatura, se supporterà N fornitori con N+1 (o successivi) system_ext e partizioni di prodotto.

Per fare ciò, ci si aspetta che i partner:

  1. Copia i file di mappatura di base generati da N system_ext e partizioni del prodotto nel relativo albero di origine.
  2. Modificare i file di mappatura secondo necessità.
  3. Installare i file di mappatura su N+1 (o versioni successive) system_ext e partizioni del prodotto.

Ad esempio, supponiamo che N system_ext abbia un tipo pubblico denominato foo_type . Quindi system_ext/etc/selinux/mapping/ N .cil nella partizione N system_ext sarà simile a:

(typeattributeset foo_type_N (foo_type))
(expandtypeattribute foo_type_N true)
(typeattribute foo_type_N)

Se bar_type viene aggiunto a N+1 system_ext e se bar_type deve essere mappato su foo_type per N fornitore, N .cil può essere aggiornato da

(typeattributeset foo_type_N (foo_type))

A

(typeattributeset foo_type_N (foo_type bar_type))

e quindi installato nella partizione N+1 system_ext. N fornitori possono continuare ad accedere a N+1 foo_type e bar_type di system_ext.

Etichettatura dei contesti SELinux

Per supportare la distinzione tra sepolicy della piattaforma e del fornitore, il sistema crea file di contesto SELinux in modo diverso per mantenerli separati.

Contesti di file

Android 8.0 ha introdotto le seguenti modifiche per file_contexts :

  • Per evitare ulteriore sovraccarico di compilazione sul dispositivo durante l'avvio, file_contexts cessa di esistere in formato binario. Sono invece file di testo di espressioni regolari leggibili come {property, service}_contexts (come erano prima della 7.0).
  • I file_contexts sono divisi tra due file:
    • plat_file_contexts
      • file_context della piattaforma Android che non ha etichette specifiche del dispositivo, ad eccezione dell'etichettatura di parti della partizione /vendor che devono essere etichettate con precisione per garantire il corretto funzionamento dei file sepolicy.
      • Deve risiedere nella partizione system in /system/etc/selinux/plat_file_contexts sul dispositivo ed essere caricato da init all'inizio insieme al fornitore file_context .
    • vendor_file_contexts
      • file_context specifico del dispositivo creato combinando file_contexts trovati nelle directory a cui punta BOARD_SEPOLICY_DIRS nei file Boardconfig.mk del dispositivo.
      • Deve essere installato in /vendor/etc/selinux/vendor_file_contexts nella partizione vendor ed essere caricato da init all'inizio insieme alla piattaforma file_context .

Contesti immobiliari

In Android 8.0, property_contexts è suddiviso in due file:

  • plat_property_contexts
    • property_context della piattaforma Android che non ha etichette specifiche del dispositivo.
    • Deve risiedere nella partizione system in /system/etc/selinux/plat_property_contexts ed essere caricato da init all'inizio insieme al fornitore property_contexts .
  • vendor_property_contexts
    • property_context specifico del dispositivo creato combinando property_contexts trovati nelle directory a cui punta BOARD_SEPOLICY_DIRS nei file Boardconfig.mk del dispositivo.
    • Deve risiedere nella partizione vendor in /vendor/etc/selinux/vendor_property_contexts ed essere caricato da init all'inizio insieme alla piattaforma property_context

Contesti di servizio

In Android 8.0, service_contexts è suddiviso tra i seguenti file:

  • plat_service_contexts
    • service_context specifico della piattaforma Android per servicemanager . service_context non ha etichette specifiche del dispositivo.
    • Deve risiedere nella partizione system in /system/etc/selinux/plat_service_contexts ed essere caricato da servicemanager all'inizio insieme al fornitore service_contexts .
  • vendor_service_contexts
    • service_context specifico del dispositivo creato combinando service_contexts trovati nelle directory a cui fa riferimento BOARD_SEPOLICY_DIRS nei file Boardconfig.mk del dispositivo.
    • Deve risiedere nella partizione vendor in /vendor/etc/selinux/vendor_service_contexts ed essere caricato da servicemanager all'inizio insieme alla piattaforma service_contexts .
    • Sebbene servicemanager cerchi questo file al momento dell'avvio, per un dispositivo TREBLE completamente compatibile, vendor_service_contexts NON DEVE esistere. Questo perché tutta l'interazione tra vendor e i processi system DEVE passare attraverso hwservicemanager / hwbinder .
  • plat_hwservice_contexts
    • Piattaforma Android hwservice_context per hwservicemanager che non ha etichette specifiche del dispositivo.
    • Deve risiedere nella partizione system in /system/etc/selinux/plat_hwservice_contexts ed essere caricato da hwservicemanager all'inizio insieme a vendor_hwservice_contexts .
  • vendor_hwservice_contexts
    • hwservice_context specifico del dispositivo creato combinando hwservice_contexts trovati nelle directory a cui punta BOARD_SEPOLICY_DIRS nei file Boardconfig.mk del dispositivo.
    • Deve risiedere nella partizione vendor in /vendor/etc/selinux/vendor_hwservice_contexts ed essere caricato da hwservicemanager all'inizio insieme a plat_service_contexts .
  • vndservice_contexts
    • service_context specifico del dispositivo per vndservicemanager creato combinando vndservice_contexts trovati nelle directory a cui punta BOARD_SEPOLICY_DIRS nel Boardconfig.mk del dispositivo.
    • Questo file deve risiedere nella partizione vendor in /vendor/etc/selinux/vndservice_contexts ed essere caricato da vndservicemanager all'avvio.

Contesti Seapp

In Android 8.0, seapp_contexts è suddiviso in due file:

  • plat_seapp_contexts
    • Piattaforma Android seapp_context che non presenta modifiche specifiche del dispositivo.
    • Deve risiedere nella partizione system in /system/etc/selinux/plat_seapp_contexts.
  • vendor_seapp_contexts
    • Estensione specifica del dispositivo alla piattaforma seapp_context creata combinando seapp_contexts trovata nelle directory indicate da BOARD_SEPOLICY_DIRS nei file Boardconfig.mk del dispositivo.
    • Deve risiedere nella partizione vendor in /vendor/etc/selinux/vendor_seapp_contexts .

Autorizzazioni MAC

In Android 8.0, mac_permissions.xml è diviso in due file:

  • Piattaforma mac_permissions.xml
    • Piattaforma Android mac_permissions.xml che non presenta modifiche specifiche del dispositivo.
    • Deve risiedere nella partizione system in /system/etc/selinux/.
  • mac_permissions.xml non basato sulla piattaforma
    • Estensione specifica del dispositivo alla piattaforma mac_permissions.xml creata da mac_permissions.xml trovata nelle directory a cui punta BOARD_SEPOLICY_DIRS nei file Boardconfig.mk del dispositivo.
    • Deve risiedere nella partizione vendor in /vendor/etc/selinux/.