Compatibilità delle politiche

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

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

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

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

  • Per il controllo delle versioni, la policy platform-public esportata verrà scritta come attributi .
  • Per semplificare la scrittura delle politiche, i tipi esportati verranno trasformati in attributi con versione come parte del processo di creazione delle politiche. 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 nei criteri della piattaforma e gli attributi con versione corrispondente per ciascuna versione della piattaforma . Ciò garantisce che quando gli oggetti vengono etichettati con un tipo, non interrompa il comportamento garantito dalla policy platform-public in una versione precedente. Questa mappatura viene mantenuta mantenendo un file di mappatura aggiornato per ogni versione della piattaforma , che conserva le informazioni sull'appartenenza degli attributi per ogni tipo esportato nella politica pubblica.

Proprietà ed etichettatura degli oggetti

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

  • I processi che richiedono l'accesso 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 le collisioni di nomi che potrebbero comportare un comportamento indefinito sul sistema (così come per l'etichettatura di SELinux). Possono verificarsi collisioni tra la piattaforma e le etichette dei fornitori per qualsiasi oggetto che ha 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 tipo/attributo di SELinux possono entrare in conflitto. Una collisione di tipo/nome attributo comporterà sempre un errore del compilatore di criteri.

Spazio dei nomi di tipo/attributo

SELinux non consente più dichiarazioni dello stesso tipo/attributo. La polizza con dichiarazioni duplicate non verrà compilata. Per evitare conflitti tra tipi e nomi di attributi, tutte le dichiarazioni dei fornitori devono avere uno spazio dei nomi che inizia con np_ .

type foo, domain; → type np_foo, domain;

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

È meglio evitare le collisioni di etichettatura utilizzando gli spazi dei nomi delle proprietà. Per identificare facilmente le proprietà della piattaforma ed evitare conflitti di nome 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 vendor.
sola lettura ro.vendor.
ro.boot.
ro.hardware.
persistente persist.vendor.

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

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

Proprietà del file

Prevenire le collisioni per i file è difficile 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 sono creati dal kernel. Per prevenire queste collisioni, segui la guida alla denominazione per i filesystem in questa sezione. Per Android 8.0, questi sono consigli senza imposizione tecnica. In futuro, queste raccomandazioni saranno 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 politica /vendor , un aggiornamento OTA solo del framework potrebbe non essere possibile.

Fornitore (/fornitore)

La politica AOSP SELinux etichetta già parti della partizione del vendor con cui la piattaforma interagisce, il che consente di scrivere regole SELinux affinché i processi della piattaforma siano in grado di parlare e/o accedere a parti della partizione del vendor . Esempi:

/vendor Etichetta fornita dalla piattaforma Processi della piattaforma a seconda dell'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 del vendor :

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

Procfs (/proc)

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

Raccomandazione: solo le etichette dei criteri della piattaforma /proc . Se i processi del vendor devono accedere ai file in /proc che sono attualmente etichettati con l'etichetta predefinita ( proc ), la politica del fornitore non dovrebbe etichettarli in modo esplicito 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à.

Debugfs (/sys/kernel/debug)

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

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

Tracefs (/sys/kernel/debug/tracing)

Tracefs può essere etichettato sia in file_contexts che in 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 usando sia file_contexts che genfscon . In Android 7.0, sia la piattaforma che il fornitore usano file_contexts e genfscon per etichettare i file in sysfs .

Raccomandazione: la piattaforma può etichettare i nodi sysfs che non sono specifici del dispositivo. In caso contrario, solo il fornitore può etichettare i file.

tmpfs (/dev)

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

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

Rootfs (/)

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

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

Dati (/dati)

I dati sono etichettati attraverso una combinazione di file_contexts e seapp_contexts .

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

Attributi di compatibilità

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

La politica è scritta principalmente in termini di tipi esistenti:

allow source_type target_type:target_class permission(s);

Questo funziona perché la politica è stata scritta con la conoscenza di tutti i tipi. Tuttavia, se la politica del fornitore e la politica della piattaforma utilizzano tipi specifici e l'etichetta di un oggetto specifico cambia solo in una di queste politiche, l'altra potrebbe contenere una politica che ha ottenuto o perso l'accesso su cui si basava 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 modificato in:

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

Sebbene la politica del fornitore rimarrebbe la stessa, 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 assegnare 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 pubbliche della piattaforma che vengono costruite come parte della policy del fornitore.

Definire le 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.
  • Possibilità di deprecare la politica . Ottenuto delineando chiaramente i set di criteri 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 policy è ancora presente nella policy del fornitore e verrà automaticamente rimossa quando/se verrà aggiornata.

Scrivibilità della politica

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

Gli attributi nelle policy pubbliche non hanno una versione, ma esistono piuttosto come un'API su cui la piattaforma e la policy del fornitore possono creare per mantenere stabile l'interfaccia tra le due partizioni. Sia gli autori di policy della piattaforma che quelli del fornitore possono continuare a scrivere la policy così com'è scritta oggi.

Politica pubblica della piattaforma esportata come allow source_foo target_bar: class perm ; è incluso come parte della politica del fornitore. Durante la compilazione (che include la versione corrispondente) si trasforma nella policy che andrà alla porzione vendor 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 riguardare le versioni precedenti. Tuttavia, la politica della piattaforma dovrà sapere quanto è indietro la politica del fornitore, includere attributi ai suoi tipi e impostare la politica corrispondente agli attributi con versione.

Differenze politiche

La creazione automatica di attributi aggiungendo _v N alla fine di ogni tipo non fa nulla senza il mapping degli attributi ai tipi tra le differenze di versione. Android mantiene una mappatura tra le versioni per gli attributi e una mappatura dei tipi a 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. È rappresentato nella polizza trasformata 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 la piattaforma ha aggiunto un nuovo tipo, cosa che può verificarsi quando si aggiungono nuove funzionalità o durante il rafforzamento dei criteri.

  • Nuova funzione . Quando il tipo etichetta un oggetto che in precedenza era inesistente (come un nuovo processo di servizio), il codice del fornitore non ha interagito in precedenza direttamente con esso, quindi non esistono criteri corrispondenti. Il nuovo attributo corrispondente al tipo non ha un attributo nella versione precedente, quindi non avrebbe bisogno di una voce nel file di mappatura destinato a quella versione.
  • Rafforzamento delle politiche . Quando il tipo rappresenta il rafforzamento delle politiche, il nuovo attributo di tipo deve ricollegarsi a una catena di attributi corrispondente a quello precedente (simile all'esempio precedente che modifica /sys/A da sysfs a sysfs_A ). Il codice del fornitore si basa su una regola che consente 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ò verificarsi quando l'oggetto sottostante:

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

Durante l'allentamento dei criteri, un tipo viene rimosso e all'oggetto etichettato con quel tipo viene assegnata un'etichetta diversa, già esistente. Ciò rappresenta un'unione di mappature di attributi: il codice del fornitore deve ancora essere in grado di accedere all'oggetto sottostante tramite l'attributo che possedeva in precedenza, 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 nuovo tipo, tranne per il fatto 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: tipi di compressione (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 pippo)

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 dei criteri che non esistono nelle versioni precedenti. Ad esempio, quando Android ha aggiunto il gestore di oggetti servicemanager che ha creato le autorizzazioni di aggiunta, trova ed elenco, i daemon dei fornitori che desiderano registrarsi con il servicemanager avevano bisogno di autorizzazioni che non erano disponibili. In Android 8.0, solo il criterio della piattaforma può aggiungere nuove classi e autorizzazioni.

Per consentire a tutti i domini che potrebbero essere stati 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 criteri che consentano l'accesso per tutti i tipi di interfaccia (politiche pubbliche), per essere sicuri che l'immagine del fornitore ottenga l'accesso. Se ciò si traduce in criteri di sicurezza inaccettabili (come potrebbe accadere con le modifiche di servicemanager), potrebbe essere potenzialmente forzato un aggiornamento del fornitore.

Classe/autorizzazioni rimosse

Questo scenario si verifica quando un gestore oggetti viene rimosso (come il gestore oggetti ZygoteConnection ) e non dovrebbe causare problemi. La classe e le autorizzazioni del gestore oggetti potrebbero rimanere definite nella politica fino a quando la versione del fornitore non la utilizza 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 policy dei fornitori in quanto 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 politica del fornitore è sempre la meno recente sul dispositivo, non è necessario convertire automaticamente tutti i tipi di fornitore in attributi nella politica. La piattaforma non si basa 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 utilizzati 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 eseguono l'aggiornamento ad Android 9 possono utilizzare i seguenti attributi, ma non i dispositivi che si avviano con Android 9.

Attributi del trasgressore

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 in base al percorso tra vendor e coredomains . I processi della piattaforma e del fornitore non devono utilizzare i file su disco per comunicare (ABI instabile). Raccomandazione:
    • Il codice del fornitore dovrebbe usare /data/vendor .
    • Il sistema non dovrebbe usare /data/vendor .
  • system_executes_vendor_violators . Attributo per tutti i domini di sistema (tranne 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 dovrebbe eseguire direttamente i file binari del fornitore. Raccomandazione:
    • Tali dipendenze della piattaforma dai binari del fornitore devono essere dietro HAL HIDL.

      O

    • coredomains che richiedono l'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 quelle considerate sufficientemente sicure per l'accesso da tali app (consulta i servizi sicuri di seguito). I due motivi principali di ciò sono:

  1. I server HwBinder non eseguono l'autenticazione del client perché HIDL attualmente non espone le informazioni sull'UID del chiamante. Anche se HIDL ha esposto tali dati, molti servizi HwBinder operano a un livello inferiore a quello delle app (come 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 clienti 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 maggiore rispetto ai componenti di system/core e hanno accesso ai livelli inferiori dello stack (fino all'hardware), aumentando così le opportunità di aggirare il modello di sicurezza di 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 comportano rischi associati al motivo n. 2.
  • hal_configstore_ISurfaceFlingerConfigs . Questo servizio è specificamente progettato per essere utilizzato da qualsiasi dominio.
  • hal_graphics_allocator_hwservice . Queste operazioni sono offerte anche dal servizio surfaceflinger Binder, a cui 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 i hwservices non considerati sicuri hanno l'attributo untrusted_app_visible_hwservice . I server HAL corrispondenti hanno l'attributo untrusted_app_visible_halserver . I dispositivi che si avviano con Android 9 NON DEVONO utilizzare nessuno dei due attributi untrusted .

Raccomandazione:

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

    O

  • Le app che richiedono l'accesso diretto agli HAL del vendor dovrebbero avere il proprio dominio di sepolicy definito dal fornitore.

Test degli attributi di file

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

Piattaforma-politica pubblica

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

I tipi e le regole vengono automaticamente tradotti nella politica 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 sono con versione). La piattaforma è responsabile della mappatura dei tipi concreti forniti 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 di policy pubblica della piattaforma e policy del fornitore soddisfa l'obiettivo del modello di architettura Android 8.0 di consentire build indipendenti di piattaforme e fornitori.

Mappatura per catene di attributi

Quando si utilizzano gli attributi per eseguire il mapping a versioni di policy, un tipo esegue il mapping a uno o più attributi, assicurando 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 politica significa generare automaticamente gli attributi con versione e assegnarli ai tipi appropriati. Nel caso comune dei tipi statici, questo è semplice: type_foo mapping 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 precedenti). I responsabili della politica 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 la compatibilità con le versioni precedenti, questa complessità deve essere gestita dal lato della piattaforma, che è l'unica partizione che può aumentare 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 mantenuto 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 aumento di MR a una versione richiede una modifica incompatibile in system/sepolicy/public ma non un aumento dell'API, la versione di sepolicy potrebbe essere: vN.1 . La versione presente in un ramo di sviluppo è una 10000.0 mai utilizzata nei dispositivi di spedizione.

Android potrebbe deprecare la versione più vecchia durante l'upreving. 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 continuano a ricevere gli aggiornamenti principali della piattaforma. Se il numero è inferiore a una determinata soglia, quella versione è obsoleta.

Impatto sulle prestazioni di più attributi

Come descritto in https://github.com/SELinuxProject/cil/issues/9 , un numero elevato di attributi assegnati a un tipo provoca problemi di prestazioni in caso di mancata cache dei criteri.

Questo è stato confermato come un problema in Android, quindi sono state apportate modifiche ad Android 8.0 per rimuovere gli attributi aggiunti al criterio dal compilatore di criteri, nonché per rimuovere gli attributi inutilizzati. Queste modifiche hanno risolto le regressioni delle prestazioni.

System_ext policy pubblica e 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 le policy pubbliche della piattaforma, il fornitore utilizza tipi e regole tradotti automaticamente negli attributi con versione, ad esempio da type in type_ N , dove N è la versione della piattaforma su cui è costruita la partizione del fornitore.

Quando le partizioni system_ext e product sono basate sulla stessa piattaforma versione N , il sistema di build genera file di mappatura di base in 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 al type con l'attributo con versione type_ N .

Nel caso in cui vengano aggiornate solo le partizioni system_ext e product, diciamo da N a N+1 (o versioni successive), mentre il fornitore rimane su N , il fornitore potrebbe perdere l'accesso ai tipi di system_ext e alle partizioni di prodotto. Per prevenire rotture, le partizioni system_ext e product dovrebbero fornire file di mappatura da tipi concreti in attributi type_ N . Ciascun partner è responsabile della manutenzione dei file di mappatura, se supporteranno N vendor con N+1 (o versioni successive) system_ext e partizioni di prodotto.

Per fare ciò, i partner devono:

  1. Copiare i file di mappatura di base generati da N partizioni system_ext e prodotto nella loro struttura 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 di prodotto.

Ad esempio, supponiamo che N system_ext abbia un tipo pubblico chiamato 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 a foo_type per N vendor, 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 di N+1 system_ext. N fornitore può continuare ad accedere a foo_type e bar_type di N+1 system_ext .

Etichettatura dei contesti di SELinux

Per supportare la distinzione tra piattaforma e policy del fornitore, il sistema crea i file di contesto SELinux in modo diverso per tenerli separati.

Contesti di file

Android 8.0 ha introdotto le seguenti modifiche per file_contexts :

  • Per evitare un ulteriore sovraccarico di compilazione sul dispositivo durante l'avvio, file_contexts cessa di esistere nel formato binario. Al contrario, sono 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 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 di system in /system/etc/selinux/plat_file_contexts sul dispositivo ed essere caricato da init all'inizio insieme al venditore 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 del vendor ed essere caricato da init all'inizio insieme alla piattaforma file_context .

Contesti immobiliari

In Android 8.0, property_contexts è diviso tra due file:

  • plat_property_contexts
    • property_context della piattaforma Android che non ha etichette specifiche per il dispositivo.
    • Deve risiedere nella partizione di system in /system/etc/selinux/plat_property_contexts ed essere caricato da init all'inizio insieme al vendor property_contexts .
  • vendor_property_contexts
    • property_context specifico del dispositivo creato combinando property_contexts trovati nelle directory indicate da BOARD_SEPOLICY_DIRS nei file Boardconfig.mk del dispositivo.
    • Deve risiedere nella partizione del 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 . Il service_context non ha etichette specifiche del dispositivo.
    • Deve risiedere nella partizione di system in /system/etc/selinux/plat_service_contexts ed essere caricato da servicemanager all'inizio insieme al fornitore service_contexts .
  • vendor_service_contexts
    • service_contexts service_context nelle directory indicate da BOARD_SEPOLICY_DIRS nei file Boardconfig.mk del dispositivo.
    • Deve risiedere nella partizione del 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 conforme, il vendor_service_contexts NON DEVE esistere. Questo perché tutte le interazioni tra il vendor ei processi system DEVONO passare attraverso hwservicemanager / hwbinder .
  • plat_hwservice_contexts
    • Piattaforma Android hwservice_context per hwservicemanager che non ha etichette specifiche del dispositivo.
    • Deve risiedere nella partizione di 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 che si trovano nelle directory indicate da BOARD_SEPOLICY_DIRS nei file Boardconfig.mk del dispositivo.
    • Deve risiedere nella partizione del 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 indicate da BOARD_SEPOLICY_DIRS nel Boardconfig.mk del dispositivo.
    • Questo file deve risiedere nella partizione del vendor in /vendor/etc/selinux/vndservice_contexts ed essere caricato da vndservicemanager all'inizio.

Contesti Seapp

In Android 8.0, seapp_contexts è diviso tra due file:

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

Autorizzazioni MAC

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

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