Questa pagina descrive come Android gestisce i problemi di compatibilità delle norme con gli aggiornamenti della piattaforma over-the-air (OTA), in cui le nuove impostazioni SELinux della piattaforma potrebbero differire dalle vecchie impostazioni SELinux del fornitore.
Proprietà ed etichettatura degli oggetti
La proprietà deve essere definita chiaramente per ogni oggetto per mantenere separate le policy della piattaforma e del fornitore. Ad esempio, se le etichette delle norme del fornitore /dev/foo
e le etichette delle norme della piattaforma /dev/foo in un OTA successivo, si verifica
un comportamento indefinito come un rifiuto imprevisto o, in modo più critico, un errore
di avvio. Per SELinux, questo si manifesta come una collisione di etichette. Il nodo del dispositivo
può avere una sola etichetta che viene risolta nell'ultima etichetta applicata.
Ne consegue che:
- I processi che necessitano dell'accesso all'etichetta applicata senza esito perdono l'accesso alla risorsa.
- I processi che ottengono l'accesso al file potrebbero interrompersi perché è stato creato il nodo del dispositivo errato.
Possono verificarsi conflitti tra le etichette della piattaforma e del fornitore per qualsiasi oggetto con un'etichetta SELinux, inclusi proprietà, servizi, processi, file e socket. Per evitare questi problemi, definisci chiaramente la proprietà di questi oggetti.
Spazio dei nomi di tipo/attributo
Oltre alle collisioni di etichette, possono verificarsi anche collisioni tra i nomi di tipi e attributi SELinux. SELinux non consente più dichiarazioni degli stessi tipi e
attributi. La compilazione di una policy con dichiarazioni duplicate non riesce. Per evitare conflitti tra tipi e nomi degli attributi, è consigliabile che tutte le dichiarazioni del fornitore inizino con il prefisso vendor_. Ad esempio, i fornitori devono utilizzare
type vendor_foo, domain; anziché type foo, domain;.
Proprietà dei file
La prevenzione delle collisioni per i file è difficile perché le norme della piattaforma e del fornitore forniscono comunemente etichette per tutti i file system. A differenza della denominazione dei tipi, lo spazio dei nomi dei file non è pratico, poiché molti di questi vengono creati dal kernel. Per evitare questi conflitti, segui le indicazioni per la denominazione dei file system in questa sezione. Per Android 8.0, questi sono consigli senza applicazione tecnica. In futuro, questi consigli verranno applicati dalla Vendor Test Suite (VTS).
Sistema (/system)
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 nelle norme del fornitore, un
aggiornamento OTA solo del framework potrebbe non essere possibile.
Fornitore (/vendor)
Il criterio SELinux AOSP etichetta già le parti della partizione vendor
con cui interagisce la piattaforma, il che consente di scrivere regole SELinux per
i processi della piattaforma in modo che possano comunicare o accedere a parti della partizione vendor. Esempi:
| /vendor path | Etichetta fornita dalla piattaforma | Processi della piattaforma a seconda dell'etichetta |
|---|---|---|
/vendor(/.*)?
|
vendor_file
|
Tutti i client HAL nel framework, ueventd e così via.
|
/vendor/framework(/.*)?
|
vendor_framework_file
|
dex2oat, appdomain e così via.
|
/vendor/app(/.*)?
|
vendor_app_file
|
dex2oat, installd, idmap e così via.
|
/vendor/overlay(/.*)
|
vendor_overlay_file
|
system_server, zygote, idmap e così via.
|
Di conseguenza, quando etichetti file aggiuntivi nella partizione vendor, devi seguire regole specifiche (applicate tramite neverallows):
vendor_filedeve essere l'etichetta predefinita per tutti i file nella partizionevendor. Il criterio della piattaforma richiede questo per accedere alle implementazioni HAL passthrough.- Tutti i nuovi
exec_typesaggiunti nella partizionevendortramite le norme del fornitore devono avere l'attributovendor_file_type. Questa operazione viene applicata tramite neverallows. - Per evitare conflitti con futuri aggiornamenti della piattaforma/del framework, evita di etichettare
file diversi da
exec_typesnella partizionevendor. - 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 solo utilizzando l'etichetta genfscon. In Android 7.0, sia i criteri
della piattaforma
sia quelli del fornitore
utilizzati genfscon per etichettare i file in procfs.
Suggerimento: solo etichette delle norme della piattaforma /proc.
Se le procedure del fornitore devono accedere ai file in /proc che
attualmente sono etichettati con l'etichetta predefinita (proc), le norme del fornitore
non devono etichettarli esplicitamente e devono invece utilizzare il tipo
generico proc per aggiungere regole per i domini dei fornitori. In questo modo, gli aggiornamenti della piattaforma
possono adattarsi alle future interfacce del kernel esposte tramite
procfs ed etichettarle esplicitamente in base alle necessità.
Debugfs (/sys/kernel/debug)
Debugfs può essere etichettato sia in file_contexts che
in genfscon. In Android 7.0 - Android 10, sia l'etichetta della piattaforma sia quella del fornitore
debugfs.
In Android 11, debugfs non può essere
acceduto o montato sui dispositivi di produzione. I produttori di dispositivi devono
rimuovere debugfs.
Tracefs (/sys/kernel/debug/tracing)
Tracefs può essere etichettato sia in file_contexts che
in genfscon. In Android 7.0, solo le etichette della piattaforma
tracefs.
Consiglio:solo la piattaforma può etichettare tracefs.
Sysfs (/sys)
I file in /sys possono essere etichettati utilizzando sia file_contexts
sia genfscon. In Android 7.0, sia la piattaforma che il fornitore utilizzano
genfscon per etichettare i file in sysfs.
Consiglio:la piattaforma potrebbe etichettare i nodi sysfs
che non sono specifici per dispositivo. In caso contrario, solo il fornitore può etichettare i file.
tmpfs (/dev)
I file in /dev potrebbero essere etichettati in file_contexts. In
Android 7.0, sia la piattaforma che i file di etichette del fornitore qui.
Consiglio:il fornitore può etichettare solo i file in
/dev/vendor (ad esempio, /dev/vendor/foo,
/dev/vendor/socket/bar).
Rootfs (/)
I file in / potrebbero essere etichettati in file_contexts. In Android
7.0, sia i file di etichette della piattaforma che del fornitore qui.
Consiglio:solo il sistema può etichettare i file in /.
Dati (/data)
I dati vengono etichettati tramite una combinazione di file_contexts e
seapp_contexts.
Consiglio:non consentire l'etichettatura del fornitore al di fuori di
/data/vendor. Solo la piattaforma può etichettare altre parti di
/data.
Versione delle etichette Genfs
A partire dal livello API fornitore 202504, le etichette SELinux più recenti assegnate con genfscon in system/sepolicy/compat/plat_sepolicy_genfs_ver.cil sono facoltative per le partizioni vendor precedenti. In questo modo, le partizioni vendor meno recenti mantengono l'implementazione SEPolicy esistente.
Questa operazione è controllata dalla variabile Makefile BOARD_GENFS_LABELS_VERSION
che è archiviata in /vendor/etc/selinux/genfs_labels_version.txt.
Esempio:
-
Nel livello API fornitore 202404, il nodo
/sys/class/udcè etichettatosysfsper impostazione predefinita. -
A partire dal livello API fornitore 202504,
/sys/class/udcè etichettatosysfs_udc.
Tuttavia, /sys/class/udc potrebbe essere in uso da partizioni vendor
che utilizzano il livello API 202404, con l'etichetta sysfs
predefinita o un'etichetta specifica del fornitore. L'etichettatura incondizionata di
/sys/class/udc come sysfs_udc potrebbe compromettere la compatibilità
con queste partizioni vendor. Se selezioni
BOARD_GENFS_LABELS_VERSION, la piattaforma continua a utilizzare le etichette e le autorizzazioni precedenti per le partizioni vendor precedenti.
BOARD_GENFS_LABELS_VERSION può essere maggiore o uguale al livello API fornitore. Ad esempio, le partizioni vendor che utilizzano il livello API 202404 possono impostare BOARD_GENFS_LABELS_VERSION su 202504 per adottare le nuove etichette introdotte in 202504. Consulta l'elenco delle
etichette genfs specifiche per il 202504.
Quando etichetta i nodi genfscon, la piattaforma deve considerare le partizioni vendor precedenti e implementare meccanismi di fallback per la compatibilità, se necessario. La piattaforma può utilizzare librerie solo per la piattaforma per eseguire query
sulla versione delle etichette genfs.
-
Per gli annunci nativi, utilizza
libgenfslabelsversion. Consultagenfslabelsversion.hper il file di intestazione dilibgenfslabelsversion. -
In Java, utilizza
android.os.SELinux.getGenfsLabelsVersion().
Norme pubbliche della piattaforma
La policy SELinux della piattaforma è suddivisa in privata e pubblica. Le norme
pubbliche della piattaforma sono costituite da tipi e attributi sempre
disponibili per un livello API fornitore,
che funge da API tra la piattaforma e il fornitore. Questo criterio è esposto agli autori di criteri dei fornitori per consentire a questi ultimi di creare file di criteri dei fornitori che, se combinati con i criteri privati della piattaforma, danno origine a un criterio completamente funzionale per un dispositivo. Il criterio pubblico della piattaforma è definito in
system/sepolicy/public.
Ad esempio, un tipo vendor_init, che rappresenta il processo init nel contesto del fornitore, è definito in system/sepolicy/public/vendor_init.te:
type vendor_init, domain;
I fornitori possono fare riferimento al tipo vendor_init per scrivere regole personalizzate
per le norme:
# Allow vendor_init to set vendor_audio_prop in vendor's init scripts
set_prop(vendor_init, vendor_audio_prop)Attributi di compatibilità
La policy SELinux è un'interazione tra i tipi di origine e di destinazione per classi di oggetti e autorizzazioni specifiche. Ogni oggetto (ad esempio processi, file) interessato dai criteri SELinux può avere un solo tipo, ma questo tipo potrebbe avere più attributi.
La policy è scritta principalmente in termini di tipi esistenti. In questo caso, sia
vendor_init che debugfs sono tipi:
allow vendor_init debugfs:dir { mounton };
Questo funziona perché le norme sono state scritte tenendo conto di tutti i tipi. Tuttavia,
se le norme del fornitore e della piattaforma utilizzano tipi specifici e l'etichetta di un
oggetto specifico cambia solo in una di queste norme, l'altra potrebbe contenere
norme che si basano sull'accesso ottenuto o perso in precedenza. Ad esempio, supponiamo
che le etichette delle norme della piattaforma contrassegnino i nodi sysfs come sysfs:
/sys(/.*)? u:object_r:sysfs:s0
Le norme relative ai fornitori concedono l'accesso a /sys/usb, etichettato come
sysfs:
allow vendor_init sysfs:chr_file rw_file_perms;
Se la policy della piattaforma viene modificata per etichettare /sys/usb come
sysfs_usb, la policy del fornitore rimane invariata, ma
vendor_init perde l'accesso a /sys/usb a causa della mancanza
di una policy per il nuovo tipo sysfs_usb:
/sys/usb u:object_r:sysfs_usb:s0
Per risolvere questo problema, Android introduce il concetto di attributi con controllo delle versioni. In fase di compilazione, il sistema di compilazione traduce automaticamente i tipi pubblici della piattaforma utilizzati nella norma del fornitore in questi attributi con controllo delle versioni. Questa traduzione è attivata da file di mapping che associano un attributo con controllo delle versioni a uno o più tipi pubblici della piattaforma.
Ad esempio, supponiamo che /sys/usb sia etichettato come sysfs
nelle norme della piattaforma 202504 e che le norme del fornitore 202504 concedano
l'accesso vendor_init a /sys/usb. In questo caso:
-
La policy del fornitore scrive una regola
allow vendor_init sysfs:chr_file rw_file_perms;, perché/sys/usbè etichettato comesysfsnella policy della piattaforma 202504. Quando il sistema di compilazione compila la policy del fornitore, traduce automaticamente la regola inallow vendor_init_202504 sysfs_202504:chr_file rw_file_perms;. Gli attributivendor_init_202504esysfs_202504corrispondono ai tipivendor_initesysfs, che sono i tipi definiti dalla piattaforma. -
Il sistema di compilazione genera un file di mappatura delle identità
/system/etc/selinux/mapping/202504.cil. Poiché le partizionisystemevendorutilizzano la stessa versione202504, il file di mappatura contiene le mappature delle identità datype_202504atype. Ad esempio,vendor_init_202504è mappato avendor_initesysfs_202504è mappato asysfs:(typeattributeset sysfs_202504 (sysfs)) (typeattributeset vendor_init_202504 (vendor_init)) ...
Quando la versione viene incrementata da 202504 a 202604, viene creato un nuovo file di mappatura per le partizioni 202504
vendor in
system/sepolicy/private/compat/202504/202504.cil, che viene
installato in /system/etc/selinux/mapping/202504.cil per le partizioni 202604
o successive system. Inizialmente, questo file di mappatura contiene
mappature delle identità, come descritto in precedenza. Se al file di mapping viene aggiunta una nuova etichetta sysfs_usb
per /sys/usb nelle norme della piattaforma 202604, il file di mapping
viene aggiornato in modo da mappare sysfs_202504 a sysfs_usb:
(typeattributeset sysfs_202504 (sysfs sysfs_usb)) (typeattributeset vendor_init_202504 (vendor_init)) ...
Questo aggiornamento consente alla regola dei criteri del fornitore convertita allow
vendor_init_202504 sysfs_202504:chr_file rw_file_perms; di concedere automaticamente
l'accesso vendor_init al nuovo tipo sysfs_usb.
Per mantenere la compatibilità con le partizioni vendor precedenti, ogni volta che viene aggiunto un nuovo tipo pubblico, questo deve essere mappato ad almeno uno degli attributi con controllo delle versioni nel file di mappatura system/sepolicy/private/compat/ver/ver.cil o essere elencato in system/sepolicy/private/compat/ver/ver.ignore.cil per indicare che non esiste un tipo corrispondente nelle versioni precedenti del fornitore.
La combinazione del criterio della piattaforma, del criterio del fornitore e del file di mapping consente al sistema di eseguire l'aggiornamento senza aggiornare il criterio del fornitore. Inoltre, la conversione negli attributi con controllo delle versioni avviene automaticamente, quindi le norme del fornitore non devono occuparsi del controllo delle versioni, ma continuare a utilizzare i tipi pubblici così come sono.
system_ext public and product public policy
A partire da Android 11, le partizioni system_ext e product
possono esportare i tipi pubblici designati nella partizione
vendor. Come le norme pubbliche della piattaforma, le norme del fornitore
utilizzano tipi e regole tradotti automaticamente negli attributi
con controllo delle versioni, ad esempio da type a
type_ver, dove ver è il livello API del fornitore
della partizione vendor.
Quando le partizioni system_ext e product si basano sulla stessa versione della piattaforma ver, il sistema di compilazione genera file di mappatura di base in system_ext/etc/selinux/mapping/ver.cil e product/etc/selinux/mapping/ver.cil, che contengono mappature delle identità da type a type_ver.
Il criterio del fornitore può accedere a type con l'attributo con controllo delle versioni
type_ver.
Nel caso in cui vengano aggiornate solo le partizioni system_ext e product, ad esempio da ver a ver+1 (o versioni successive), mentre la partizione vendor rimane a ver, le norme del fornitore potrebbero perdere l'accesso ai tipi di partizioni system_ext e product. Per evitare interruzioni, le partizioni
system_ext e product devono fornire
file di mapping dai tipi concreti agli attributi
type_ver. Ogni partner è responsabile della manutenzione dei file di mapping, se supporta la partizione ver vendor con le partizioni ver+1 (o versioni successive) system_ext e product.
Per installare i file di mapping nelle partizioni system_ext e product, gli implementatori di dispositivi o i fornitori devono:
- Copia i file di mapping di base generati dalle partizioni ver
system_exteproductnell'albero di origine. - Modifica i file di mappatura in base alle necessità.
-
Installa i
file di mapping su ver+1 (o versioni successive)
system_exte partizioniproduct.
Ad esempio, supponiamo che la partizione 202504 system_ext abbia un tipo pubblico denominato foo_type. Poi
system_ext/etc/selinux/mapping/202504.cil
nella partizione 202504 system_ext sarà simile a questo:
(typeattributeset foo_type_202504 (foo_type)) (expandtypeattribute foo_type_202504 true) (typeattribute foo_type_202504)
Se bar_type viene aggiunto alla partizione 202604 system_ext e se
bar_type deve essere mappato a foo_type per la partizione 202504
vendor, 202504.cil può essere aggiornato da
(typeattributeset foo_type_202504 (foo_type)) a
(typeattributeset foo_type_202504 (foo_type bar_type))
e poi installato nella partizione 202604 system_ext. La partizione 202504
vendor può continuare ad accedere a foo_type e bar_type della partizione 202604
system_ext.
Modifiche agli attributi per Android 9
I dispositivi che eseguono l'upgrade ad Android 9 possono utilizzare i seguenti attributi, ma i dispositivi che vengono lanciati con Android 9 non devono farlo.
Attributi del violatore
Android 9 include i seguenti attributi correlati al dominio:
data_between_core_and_vendor_violators. Attributo per tutti i domini che violano il requisito di non condividere file per percorso travendorecoredomains. I processi della piattaforma e del fornitore non devono utilizzare file su disco per comunicare (ABI instabile). Consiglio:- Il codice fornitore deve utilizzare
/data/vendor. - Il sistema non deve utilizzare
/data/vendor.
- Il codice fornitore deve utilizzare
- Attributo
system_executes_vendor_violators. per tutti i domini di sistema (ad eccezione diiniteshell domains) che violano il requisito di non eseguire i binari del fornitore. L'esecuzione dei binari del fornitore ha un'API instabile. La piattaforma non deve eseguire direttamente i binari del fornitore. Consiglio:- Queste dipendenze della piattaforma dai binari del fornitore devono trovarsi dietro gli HAL HIDL.
OPPURE
coredomainsche devono accedere ai binari del fornitore devono essere spostati nella partizionevendore quindi non essere piùcoredomain.
- Queste dipendenze della piattaforma dai binari del fornitore devono trovarsi dietro gli HAL HIDL.
Attributi non attendibili
Le app non attendibili che ospitano codice arbitrario non devono avere accesso ai servizi HwBinder, ad eccezione di quelli considerati sufficientemente sicuri per l'accesso da parte di queste app (vedi i servizi sicuri di seguito). I due motivi principali sono:
- I server HwBinder non eseguono l'autenticazione del client perché HIDL attualmente non espone le informazioni sull'UID del chiamante. Anche se HIDL esponesse questi dati, molti servizi HwBinder operano a un livello inferiore a quello delle app (ad esempio, HAL) o non devono fare affidamento sull'identità dell'app per l'autorizzazione. Pertanto, per sicurezza, l'ipotesi predefinita è che ogni servizio HwBinder tratti tutti i suoi client come ugualmente autorizzati a eseguire le operazioni offerte dal servizio.
- I server HAL (un sottoinsieme di servizi HwBinder) contengono codice con un tasso di incidenza più elevato di problemi di sicurezza rispetto ai componenti
system/coree hanno accesso ai livelli inferiori dello stack (fino all'hardware), aumentando così le opportunità di aggirare il modello di sicurezza di Android.
Servizi di casseforti
I servizi sicuri includono:
same_process_hwservice. Questi servizi (per definizione) vengono eseguiti nel processo del client e pertanto 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 è progettato specificamente per l'utilizzo da parte di qualsiasi dominio.hal_graphics_allocator_hwservice. Queste operazioni sono offerte anche dal servizio Bindersurfaceflinger, a cui le app sono autorizzate ad accedere.hal_omx_hwservice. Si tratta di una versione HwBinder del servizio Bindermediacodec, a cui le app possono accedere.hal_codec2_hwservice. Questa è una versione più recente dihal_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 vengono lanciati
con Android 9 NON DEVONO utilizzare
l'attributo untrusted.
Consiglio:
- Le app non attendibili devono invece comunicare con un servizio di sistema che comunica con l'HAL HIDL del fornitore. Ad esempio, le app possono comunicare con
binderservicedomain, poimediaserver(che è unbinderservicedomain) a sua volta comunica conhal_graphics_allocator.OPPURE
- Le app che richiedono l'accesso diretto agli HAL
vendordevono avere il proprio dominio sepolicy definito dal fornitore.
Test degli attributi dei 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).
Etichettatura dei contesti SELinux
Per supportare la distinzione tra sepolicy della piattaforma e del fornitore, il sistema crea i file di contesto SELinux in modo diverso per mantenerli separati.
Contesti dei file
Android 8.0 ha introdotto le seguenti modifiche per file_contexts:
- Per evitare un sovraccarico di compilazione aggiuntivo sul dispositivo durante l'avvio,
file_contextsnon esisteranno più in formato binario. ma sono file di testo di espressioni regolari leggibili, come{property, service}_contexts(come nelle versioni precedenti alla 7.0). - I
file_contextssono suddivisi in due file:plat_file_contexts- Piattaforma Android
file_contextche non ha etichette specifiche del dispositivo, ad eccezione dell'etichettatura di parti della partizione/vendorche deve essere etichettata con precisione per garantire il corretto funzionamento dei file sepolicy. - Deve risiedere nella partizione
systemin/system/etc/selinux/plat_file_contextssul dispositivo ed essere caricato dainitall'inizio insieme alfile_contextdel fornitore.
- Piattaforma Android
vendor_file_contextsfile_contextspecifico del dispositivo creato combinandofile_contextstrovato nelle directory indicate daBOARD_SEPOLICY_DIRSnei fileBoardconfig.mkdel dispositivo.- Deve essere installato in
/vendor/etc/selinux/vendor_file_contextsnella partizionevendore caricato dainitall'inizio insieme alla piattaformafile_context.
Contesti delle proprietà
In Android 8.0, property_contexts è suddiviso in due file:
plat_property_contexts- Piattaforma Android
property_contextche non ha etichette specifiche per dispositivo. - Deve risiedere nella partizione
systemin/system/etc/selinux/plat_property_contextsed essere caricato dainitall'inizio insieme al fornitoreproperty_contexts.
- Piattaforma Android
vendor_property_contextsproperty_contextspecifico del dispositivo creato combinandoproperty_contextstrovati nelle directory indicate daBOARD_SEPOLICY_DIRSnei fileBoardconfig.mkdel dispositivo.- Deve risiedere nella partizione
vendorall'indirizzo/vendor/etc/selinux/vendor_property_contextsed essere caricato dainitall'inizio insieme alla piattaformaproperty_context
Contesti di servizio
In Android 8.0, service_contexts è suddiviso nei seguenti file:
plat_service_contextsservice_contextspecifici per la piattaforma Android perservicemanager.service_contextnon ha etichette specifiche per dispositivo.- Deve risiedere nella partizione
systemin/system/etc/selinux/plat_service_contextsed essere caricato daservicemanagerall'inizio insieme al fornitoreservice_contexts.
vendor_service_contextsservice_contextspecifico del dispositivo creato combinandoservice_contextstrovato nelle directory indicate daBOARD_SEPOLICY_DIRSnei fileBoardconfig.mkdel dispositivo.- Deve risiedere nella partizione
vendorall'indirizzo/vendor/etc/selinux/vendor_service_contextsed essere caricato daservicemanagerall'inizio insieme alla piattaformaservice_contexts. - Sebbene
servicemanagercerchi questo file all'avvio, per un dispositivoTREBLEcompletamente conforme, il filevendor_service_contextsNON deve esistere. Questo perché tutta l'interazione travendoresystemdeve passare attraversohwservicemanager/hwbinder.
plat_hwservice_contexts- Piattaforma Android
hwservice_contextperhwservicemanagerche non ha etichette specifiche per il dispositivo. - Deve risiedere nella partizione
systemin/system/etc/selinux/plat_hwservice_contextsed essere caricato dahwservicemanagerall'inizio insieme avendor_hwservice_contexts.
- Piattaforma Android
vendor_hwservice_contextshwservice_contextspecifico del dispositivo creato combinandohwservice_contextstrovato nelle directory indicate daBOARD_SEPOLICY_DIRSnei fileBoardconfig.mkdel dispositivo.- Deve risiedere nella partizione
vendorin/vendor/etc/selinux/vendor_hwservice_contextsed essere caricato dahwservicemanagerall'inizio insieme aplat_service_contexts.
vndservice_contextsservice_contextspecifico del dispositivo pervndservicemanagercreato combinandovndservice_contextstrovati nelle directory indicate daBOARD_SEPOLICY_DIRSinBoardconfig.mkdel dispositivo.- Questo file deve risiedere nella partizione
vendorin/vendor/etc/selinux/vndservice_contextsed essere caricato davndservicemanagerall'inizio.
Contesti Seapp
In Android 8.0, seapp_contexts è suddiviso in due file:
plat_seapp_contexts- Piattaforma Android
seapp_contextsenza modifiche specifiche per il dispositivo. - Deve risiedere nella partizione
systemin/system/etc/selinux/plat_seapp_contexts.
- Piattaforma Android
vendor_seapp_contexts- Estensione specifica del dispositivo alla piattaforma
seapp_contextcreata combinandoseapp_contextstrovati nelle directory indicate daBOARD_SEPOLICY_DIRSnei fileBoardconfig.mkdel dispositivo. - Deve risiedere nella partizione
vendorall'indirizzo/vendor/etc/selinux/vendor_seapp_contexts.
- Estensione specifica del dispositivo alla piattaforma
Autorizzazioni MAC
In Android 8.0, mac_permissions.xml è suddiviso in due file:
- Piattaforma
mac_permissions.xml- Piattaforma Android
mac_permissions.xmlsenza modifiche specifiche del dispositivo. - Deve risiedere nella partizione
systemin/system/etc/selinux/.
- Piattaforma Android
- Non-Platform
mac_permissions.xml- Estensione specifica del dispositivo alla piattaforma
mac_permissions.xmlcreata damac_permissions.xmltrovata nelle directory indicate daBOARD_SEPOLICY_DIRSnei fileBoardconfig.mkdel dispositivo. - Deve risiedere nella partizione
vendorin/vendor/etc/selinux/.
- Estensione specifica del dispositivo alla piattaforma
Modifiche alla memoria condivisa per Android 17
A partire da Android 17, i dispositivi lanciati con le seguenti proprietà devono attivare la funzionalità dei criteri memfd_class e aggiornare i criteri relativi alla memoria condivisa per supportare gli oggetti della classe memfd_file:
- Livello API fornitore 202604 o superiore per offrire a fornitori e OEM l'opportunità di aggiornare le proprie norme per i fornitori in modo da supportare
memfd. Consente inoltre ai dispositivi esistenti di eseguire l'upgrade a versioni più recenti di Android senza richiedere un aggiornamento della partizione del fornitore. android16-6.12o versioni successive, poiché questi kernel supportano la funzionalitàmemfd_class, necessaria per l'implementazione di policy granulari permemfd.
Attiva la funzionalità della policy memfd_class
Fino a poco tempo fa, SELinux etichettava un memfd come file dello stesso tipo del file system di supporto, ovvero tmpfs. In questo modo, dal punto di vista delle norme, era impossibile distinguere un memfd da un altro file su un montaggio tmpfs. Ora, SELinux etichetta un memfd con il contesto di sicurezza del processo di allocazione e memfds vengono trattati come oggetti della classe memfd_file. Questa funzionalità è protetta dalla funzionalità dei criteri memfd_class per preservare la compatibilità con le versioni precedenti degli ambienti userspace.
Per abilitare la funzionalità della policy memfd_class, crea un file policy_capabilities in BOARD_VENDOR_SEPOLICY_DIRS. Il file deve contenere la seguente voce:
# $BOARD_VENDOR_SEPOLICY_DIRS/*/policy_capabilities
policycap memfd_class;Quindi, ricompila le immagini ed esegui il flashing sul dispositivo per verificare che la funzionalità sia attivata.
Verifica che la funzionalità del criterio memfd_class sia abilitata
Utilizza il seguente comando per controllare lo stato della funzionalità della policy memfd_class:
adb shell 'cat /sys/fs/selinux/policy_capabilities/memfd_class'
Se il risultato è 1, la funzionalità del criterio memfd_class è attivata. In caso contrario, non è abilitata.
Esegui la transizione della policy esistente a memfd
Alcuni processi utilizzavano la macro tmpfs_domain() nella propria policy per accedere a memfds e assegnare uno spazio dei nomi, ad esempio:
# foo.te
tmpfs_domain(foo)Ciò si traduce in:
# foo.te type_transition foo tmpfs:file foo_tmpfs; allow foo foo_tmpfs:file { read write getattr map };
e consente di elaborare bar la procedura di accesso foo's memfds come segue:
# bar.te allow bar foo_tmpfs:file { read write getattr map };
Con la funzionalità dei criteri memfd_class attivata, la macro tmpfs_domain() non è più necessaria, in quanto i criteri della piattaforma sono stati aggiornati per consentire a qualsiasi processo di creare e utilizzare il proprio memfds, come mostrato di seguito:
# system/sepolicy/private/domain.te allow domain self:memfd_file { create read write getattr map };
e memfds creato dal processo foo può essere accessibile dal processo bar come segue:
# bar.te allow bar foo:memfd_file { read write getattr map };
Le norme della piattaforma sono state aggiornate per tenere conto degli utilizzi esistenti di memfd. Tuttavia, le norme specifiche per fornitori e dispositivi che utilizzano le etichette tmpfs devono essere aggiornate per utilizzare memfd_file. Se le norme sono condivise tra SoC o dispositivi che non hanno il livello API fornitore 202604 o versioni successive, per garantire la compatibilità è consigliabile mantenere le norme tmpfs legacy insieme alle nuove norme memfd_file.
Identificare i rifiuti AVC correlati a memfd
I rifiuti correlati a Memfd possono essere recuperati utilizzando il seguente comando:
adb shell logcat -d -b events | grep memfd
avc denials con tmpfs come target
L'esempio seguente mostra un rifiuto avc riscontrato da un processo che ha tentato di scrivere in un memfd per cui non aveva l'autorizzazione di scrittura:
audit(0.0:539): avc: denied { write } for comm="binder:665_1" name="memfd:MessageQueue"
dev="tmpfs" ino=8324 scontext=u:r:mediacodec:s0 tcontext=u:object_r:tmpfs:s0 tclass=file
permissive=0
Quando la funzionalità del criterio memfd_class è attivata, il contesto di destinazione di un memfd è il contesto di sicurezza del processo di allocazione, non tmpfs, e la classe di destinazione è memfd_file, non file. Pertanto, se osservi avc rifiuti correlati a memfd, dove memfd in questione è etichettato come file tmpfs, la funzionalità delle norme memfd_class non è abilitata.
avc denials con memfd_file come classe target
L'esempio seguente mostra un rifiuto avc riscontrato da un processo che tenta di scrivere in un memfd per cui non disponeva dell'autorizzazione di scrittura. È stata attivata la funzionalità di policy memfd_class, nonché una riga aggiuntiva emessa da logd dopo il rifiuto con lo stesso timestamp:
audit(0.0:86): avc: denied { read } for
path=2F6D656D66643A4D6564696142756666657247726F7570202864656C6574656429 ino=512 dev=""
scontext=u:r:mediaserver:s0 tcontext=u:object_r:mediaextractor:s0 tclass=memfd_file
auditd : Decoded path for audit(0.0:86): /memfd:MediaBufferGroup (deleted)
Il timestamp corrispondente indica che Decoded path for … log è correlato al rifiuto avc con il timestamp 0.0.86. Questo log decodifica la stringa esadecimale dal valore del percorso nel rifiuto avc e fornisce il nome della regione di memoria memfd, che può essere utile per capire quale buffer viene condiviso. Il contesto di origine e quello di destinazione sono utili per capire quali processi devono condividere la memoria. Dall'esempio precedente, è chiaro che il processo mediaserver deve essere in grado di accedere a memfds di mediaextractor. Pertanto, la norma appropriata è:
# mediaserver.te allow mediaserver mediaextractor:memfd_file { getattr read write map };
Aggiornamenti dei domini di sicurezza in Android 17
L'API ASharedMemory_create() in Android 17 implementa la logica condizionale per selezionare tra il driver ashmem legacy e il framework memfd per le allocazioni di memoria condivisa.
Per i dispositivi che soddisfano i requisiti memfd (livello API fornitore 202604 o superiore e kernel android16-6.12 o successivo), l'API valuta targetSdkVersion dell'app chiamante. Se la versione dell'SDK target è 37 o successive, viene allocato un memfd. In questo modo, gli sviluppatori possono risolvere i problemi che riscontrano durante l'upgrade della versione dell'SDK di destinazione.
Se il dispositivo non soddisfa i prerequisiti di memfd's, ASharedMemory esegue il fallback ad ashmem. In questo modo viene mantenuta la compatibilità dei dispositivi aggiornati con partizioni o kernel del fornitore precedenti.
Per applicare questa transizione, le norme SELinux della piattaforma impediscono alle app che hanno come target la versione 37 o successive dell'SDK nei domini di sicurezza platform_app, priv_app e untrusted_app di aprire /dev/ashmem e richiamare i comandi ioctl ashmem su memfd. Ciò si ottiene dividendo questi domini dell'app in base alla versione dell'SDK target. Vengono introdotti i domini di sicurezza platform_app_36, priv_app_36 e untrusted_app_34, che insieme ad altri domini delle app mantengono le autorizzazioni di apertura di ashmem e la possibilità di richiamare i comandi ioctl di ashmem su memfds.
In una futura release di Android, l'insieme di app che mantengono le autorizzazioni per aprire il dispositivo ashmem e richiamare i comandi ioctl ashmem su memfds viene ridotto a platform_app_36, priv_app_36 e untrusted_app_34 e ai domini delle app non attendibili per le versioni precedenti dell'SDK.
Le norme SELinux personalizzate del fornitore o dell'OEM per le app che bloccano la versione dell'SDK di destinazione devono essere aggiornate in modo da essere in linea con queste modifiche al dominio, come descritto nelle sezioni seguenti.
Aggiornamenti del dominio SELinux di platform_app
Il dominio platform_app viene suddiviso in base all'targetSdkVersion dell'app. Alle app della piattaforma che hanno come target la versione 37 o successive dell'SDK viene assegnato il dominio platform_app, mentre quelle che hanno come target la versione 36 o precedenti dell'SDK utilizzano platform_app_36. Il dominio platform_app_36 mantiene la possibilità di aprire /dev/ashmem per la compatibilità con le versioni precedenti. Per semplificare la gestione delle policy in entrambi i domini, utilizza l'attributo platform_app_all.
Considera il caso in cui l'app della piattaforma sample-plat-app deve leggere e scrivere da e verso /dev/foo_device. La policy SELinux del fornitore esistente potrebbe essere simile alla seguente:
# This will only allow sample-plat-app to access the device if it # is placed in the platform_app domain (i.e. target SDK version is 37 or higher). allow platform_app foo_device:chr_file rw_file_perms;
Tuttavia, se sample-plat-app è bloccato alla versione 36 dell'SDK di destinazione, viene inserito nel dominio platform_app_36 e i criteri SELinux precedenti non vengono applicati. Viene osservato il seguente rifiuto AVC:
auditd : type=1400 audit(0.0:11): avc: denied { read write } for comm="sample-plat-app" path="/dev/foo_device" dev="tmpfs" ino=1609 scontext=u:r:platform_app_36:s0:c512,c768 tcontext=u:object_r:foo_device:s0 tclass=chr_file permissive=0
Per risolvere il problema, il criterio può essere aggiornato in questo modo, poiché l'app deve sempre avere accesso al nodo del dispositivo:
# This allows sample-plat-app to access the device independent of # target SDK version. allow platform_app_all foo_device:chr_file rw_file_perms;
Potrebbero verificarsi situazioni in cui platform_app_all potrebbe non funzionare. Ad esempio, se la macro hal_client_domain() viene utilizzata con platform_app_all, la compilazione del criterio non riesce. Questo perché platform_app_all è un attributo e hal_client_domain() tenterebbe di collegarvi un altro attributo, il che non è possibile:
# platform_app.te
hal_client_domain(platform_app, hal_foo)
In questi scenari, è necessario utilizzare direttamente il tipo platform_app_36, pertanto le norme hanno i seguenti contenuti:
# platform_app.te hal_client_domain(platform_app, hal_foo) # platform_app_36.te hal_client_domain(platform_app_36, hal_foo)
Aggiornamenti del dominio SELinux priv_app
Il dominio priv_app viene suddiviso in base all'targetSdkVersion dell'app. Alle app privilegiate che hanno come target la versione 37 o successive dell'SDK viene assegnato il dominio priv_app, mentre quelle che hanno come target la versione 36 o precedenti dell'SDK utilizzano priv_app_36. Il dominio priv_app_36 mantiene la possibilità di aprire /dev/ashmem per la compatibilità con le versioni precedenti. Per semplificare la gestione delle policy in entrambi i domini, utilizza l'attributo priv_app_all.
Considera il caso in cui l'app della piattaforma sample-priv-app deve leggere e scrivere da e verso /dev/foo_device. La policy SELinux del fornitore esistente potrebbe essere simile alla seguente:
# This will only allow sample-priv-app to access the device if it # is placed in the priv_app domain (i.e. target SDK version is 37 or higher). allow priv_app foo_device:chr_file rw_file_perms;
Tuttavia, se sample-priv-app è bloccato alla versione 36 dell'SDK di destinazione, viene inserito nel dominio priv_app_36 e i criteri SELinux precedenti non vengono applicati. Viene osservato il seguente rifiuto AVC:
auditd : type=1400 audit(0.0:11): avc: denied { read write } for comm="sample-priv-app" path="/dev/foo_device" dev="tmpfs" ino=1609 scontext=u:r:priv_app_36:s0:c512,c768 tcontext=u:object_r:foo_device:s0 tclass=chr_file permissive=0
Per risolvere il problema, il criterio può essere aggiornato in questo modo, poiché l'app deve sempre avere accesso al nodo del dispositivo:
# This allows sample-priv-app to access the device independent of # target SDK version. allow priv_app_all foo_device:chr_file rw_file_perms;
Potrebbero verificarsi situazioni in cui priv_app_all potrebbe non funzionare. Ad esempio, se la macro hal_client_domain() viene utilizzata con priv_app_all, la compilazione del criterio non andrà a buon fine. Questo perché priv_app_all è un attributo e hal_client_domain() tenterebbe di collegarvi un altro attributo, il che non è possibile:
# priv_app.te
hal_client_domain(priv_app, hal_foo)
In questi scenari, è necessario utilizzare direttamente il tipo priv_app_36, quindi i file delle norme avranno un aspetto simile a questo:
# priv_app.te hal_client_domain(priv_app, hal_foo) # priv_app_36.te hal_client_domain(priv_app_36, hal_foo)
Aggiornamenti del dominio SELinux untrusted_app
Il dominio untrusted_app viene suddiviso in base all'targetSdkVersion dell'app. Alle app non attendibili che hanno come target la versione 37 o successive dell'SDK viene assegnato il dominio untrusted_app, mentre a quelle che hanno come target le versioni 34-36 dell'SDK viene assegnato il nuovo dominio untrusted_app_34. Il dominio untrusted_app_34, così come i domini untrusted_app_X, dove "X" è una versione precedente dell'SDK target, mantengono la possibilità di aprire `/dev/ashmem` per la compatibilità con le versioni precedenti.