Personalizza SELinux

Dopo aver integrato il livello di base della funzionalità SELinux e aver esaminato attentamente i risultati, puoi aggiungere le tue impostazioni dei criteri per coprire le tue personalizzazioni del sistema operativo Android. Questi criteri devono comunque soddisfare i requisiti del Programma di compatibilità Android e non devono rimuovere le impostazioni SELinux predefinite.

I produttori non devono rimuovere le norme SELinux esistenti. In caso contrario, rischia di interrompere l'implementazione di Android SELinux e le app che governa. Sono incluse le app di terze parti che probabilmente dovranno essere migliorate per essere conformi e operative. Le app non devono richiedere modifiche per continuare a funzionare sui dispositivi abilitati per SELinux.

Quando inizi a personalizzare SELinux, ricordati di:

  • Scrivi criterio SELinux per tutti i nuovi daemon
  • Utilizza i domini predefiniti, se opportuno
  • Assegna un dominio a qualsiasi processo generato come servizio init
  • Acquisisci familiarità con le macro prima di scrivere le norme
  • Inviare le modifiche alle norme di base ad AOSP

Inoltre, ricordati di non:

  • Crea criterio incompatibile
  • Consentire la personalizzazione delle norme per gli utenti finali
  • Consenti personalizzazioni dei criteri MDM
  • Spaventare gli utenti con violazioni delle norme
  • Aggiungere backdoor

Per requisiti specifici, consulta la sezione Funzionalità di sicurezza del kernel del documento sulla definizione di compatibilità Android.

SELinux utilizza un approccio di tipo whitelist, il che significa che tutto l'accesso deve essere esplicitamente consentito nel criterio per essere concesso. Poiché il criterio SELinux predefinito di Android supporta già il progetto open source Android, non è necessario modificare le impostazioni di SELinux in alcun modo. Se personalizzi le impostazioni SELinux, fai molta attenzione a non danneggiare le app esistenti. Per iniziare:

  1. Usa il kernel Android più recente.
  2. Adotta il principio del privilegio minimo.
  3. Rivolgiti solo per le tue aggiunte ad Android. Il criterio predefinito funziona automaticamente con la base di codice del progetto Android Open Source.
  4. Suddividi i componenti software in moduli che svolgono singole attività.
  5. Crea criteri SELinux che isolino queste attività da funzioni non correlate.
  6. Inserisci questi criteri nei file *.te (l'estensione per i file di codice sorgente dei criteri SELinux) all'interno della directory /device/manufacturer/device-name/sepolicy e utilizza le variabili BOARD_SEPOLICY per includerli nella compilazione.
  7. Rendi inizialmente permissivi i nuovi domini. Ciò viene fatto utilizzando una dichiarazione permissiva nel file .te del dominio.
  8. Analizza i risultati e perfeziona le definizioni di dominio.
  9. Rimuovi la dichiarazione permissiva quando non vengono visualizzati ulteriori rifiuti nelle build di userdebug.

Dopo aver integrato la modifica del criterio SELinux, aggiungi un passaggio al flusso di lavoro di sviluppo per garantire la compatibilità con SELinux in futuro. In un processo di sviluppo software ideale, il criterio SELinux cambia solo quando cambia il modello software e non l'implementazione effettiva.

Quando inizi a personalizzare SELinux, controlla prima le aggiunte ad Android. Se hai aggiunto un componente che esegue una nuova funzione, assicurati che il componente soddisfi i criteri di sicurezza di Android, nonché eventuali criteri associati creati dall'OEM, prima di attivare la modalità di applicazione.

Per evitare problemi inutili, è meglio avere un testo troppo ampio e compatibile che troppo restrittivo e incompatibile, con la conseguenza di interrompere le funzioni del dispositivo. Al contrario, se le tue modifiche saranno utili per altri, dovresti inviarle al criterio SELinux predefinito come patch. Se la patch viene applicata al criterio di sicurezza predefinito, non dovrai apportare questa modifica con ogni nuova release di Android.

Dichiarazioni di norme di esempio

SELinux si basa sul linguaggio di programmazione M4 e pertanto supporta una serie di macro per farti risparmiare tempo.

Nell'esempio seguente, a tutti i domini viene concesso l'accesso in lettura o scrittura in /dev/null e in lettura da /dev/zero.

# Allow read / write access to /dev/null
allow domain null_device:chr_file { getattr open read ioctl lock append write};

# Allow read-only access to /dev/zero
allow domain zero_device:chr_file { getattr open read ioctl lock };

La stessa istruzione può essere scritta con le macro *_file_perms SELinux (abbreviazione):

# Allow read / write access to /dev/null
allow domain null_device:chr_file rw_file_perms;

# Allow read-only access to /dev/zero
allow domain zero_device:chr_file r_file_perms;

Norme di esempio

Di seguito è riportato un esempio completo di criterio per DHCP:

type dhcp, domain;
permissive dhcp;
type dhcp_exec, exec_type, file_type;
type dhcp_data_file, file_type, data_file_type;

init_daemon_domain(dhcp)
net_domain(dhcp)

allow dhcp self:capability { setgid setuid net_admin net_raw net_bind_service
};
allow dhcp self:packet_socket create_socket_perms;
allow dhcp self:netlink_route_socket { create_socket_perms nlmsg_write };
allow dhcp shell_exec:file rx_file_perms;
allow dhcp system_file:file rx_file_perms;
# For /proc/sys/net/ipv4/conf/*/promote_secondaries
allow dhcp proc_net:file write;
allow dhcp system_prop:property_service set ;
unix_socket_connect(dhcp, property, init)

type_transition dhcp system_data_file:{ dir file } dhcp_data_file;
allow dhcp dhcp_data_file:dir create_dir_perms;
allow dhcp dhcp_data_file:file create_file_perms;

allow dhcp netd:fd use;
allow dhcp netd:fifo_file rw_file_perms;
allow dhcp netd:{ dgram_socket_class_set unix_stream_socket } { read write };
allow dhcp netd:{ netlink_kobject_uevent_socket netlink_route_socket
netlink_nflog_socket } { read write };

Analizziamo l'esempio:

Nella prima riga, la dichiarazione del tipo, il demone DHCP eredita dal criterio di sicurezza di base (domain). Dagli esempi di dichiarazione precedenti, DHCP può leggere e scrivere in /dev/null.

Nella seconda riga, DHCP è identificato come dominio permissivo.

Nella riga init_daemon_domain(dhcp), il criterio indica che DHCP viene generato da init ed è autorizzato a comunicare con questo.

Nella riga net_domain(dhcp), il criterio consente a DHCP di usare le funzionalità di rete comuni del dominio net, come la lettura e la scrittura di pacchetti TCP, la comunicazione su socket e l'esecuzione di richieste DNS.

Nella riga allow dhcp proc_net:file write;, il criterio indica che DHCP può scrivere su file specifici in /proc. Questa riga mostra la classificazione granulare dei file di SELinux. Utilizza l'etichetta proc_net per limitare l'accesso in scrittura solo ai file in /proc/sys/net.

L'ultimo blocco dell'esempio che inizia con allow dhcp netd:fd use; mostra in che modo le app possono interagire tra loro. Il criterio indica che DHCP e netd possono comunicare tra loro tramite descrittori file, file FIFO, socket datagram e socket stream UNIX. DHCP può leggere e scrivere solo nelle socket di datagrammi e nelle socket stream UNIX, senza crearle o aprirle.

Controlli disponibili

Classe Autorizzazione
file
ioctl read write create getattr setattr lock relabelfrom relabelto append
unlink link rename execute swapon quotaon mounton
directory
add_name remove_name reparent search rmdir open audit_access execmod
presa
ioctl read write create getattr setattr lock relabelfrom relabelto append bind
connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg
name_bind
filesystem
mount remount unmount getattr relabelfrom relabelto transition associate
quotamod quotaget
processo
fork transition sigchld sigkill sigstop signull signal ptrace getsched setsched
getsession getpgid setpgid getcap setcap share getattr setexec setfscreate
noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem
execstack execheap setkeycreate setsockcreate
sicurezza
compute_av compute_create compute_member check_context load_policy
compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot
read_policy
funzionalità
chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap
linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock
ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin
sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write
audit_control setfcap

ALTRO

E ANCORA

Regole neverallow

Le regole neverallow di SELinux vietano un comportamento che non dovrebbe mai verificarsi. Con i test di compatibilità, le regole SELinux neverallow vengono ora applicate su tutti i dispositivi.

Le seguenti linee guida hanno lo scopo di aiutare i produttori a evitare errori correlati alle regole neverallow durante la personalizzazione. I numeri di regole usati qui corrispondono ad Android 5.1 e sono soggetti a modifiche in base alla release.

Regola 48: neverallow { domain -debuggerd -vold -dumpstate -system_server } self:capability sys_ptrace;
consulta la pagina man di ptrace. La funzionalità sys_ptrace consente di ptrace qualsiasi processo, il che consente un notevole controllo sugli altri processi e dovrebbe appartenere solo ai componenti di sistema designati, descritti nella regola. La necessità di questa funzionalità spesso indica la presenza di qualcosa che non è destinato agli utenti per build o funzionalità non necessarie. Rimuovi il componente non necessario.

Regola 76: neverallow { domain -appdomain -dumpstate -shell -system_server -zygote } { file_type -system_file -exec_type }:file execute;
Questa regola ha lo scopo di impedire l'esecuzione di codice arbitrario sul sistema. Nello specifico, afferma che viene eseguito solo il codice su /system, il che consente garanzie di sicurezza grazie a meccanismi come l'avvio verificato. Spesso, la soluzione migliore quando si verifica un problema con questa neverallow regola è spostare il codice in violazione nella /system partizione.

Personalizzare SEPolicy in Android 8.0 e versioni successive

Questa sezione fornisce le linee guida per i criteri SELinux del fornitore in Android 8.0 e versioni successive, inclusi dettagli sulle estensioni SEPolicy e SEPolicy di Android Open Source Project (AOSP). Per ulteriori informazioni su come il criterio SELinux viene mantenuto compatibile tra le partizioni e le versioni di Android, consulta Compatibilità.

Posizionamento dei criteri

In Android 7.0 e versioni precedenti, i produttori di dispositivi potevano aggiungere criteri a BOARD_SEPOLICY_DIRS, inclusi criteri pensati per integrare i criteri AOSP su diversi tipi di dispositivi. In Android 8.0 e versioni successive, l'aggiunta di un criterio a BOARD_SEPOLICY_DIRS lo inserisce solo nell'immagine del fornitore.

In Android 8.0 e versioni successive, i criteri esistono nelle seguenti posizioni in AOSP:

  • system/sepolicy/public. Sono incluse le norme esportate per l'utilizzo nelle norme specifiche del fornitore. Tutto rientra nell'infrastruttura di compatibilità di Android 8.0. Le norme pubbliche sono destinate a essere mantenute nelle release, pertanto puoi includere qualsiasi cosa /public nei tuoi criteri personalizzati. Per questo motivo, il tipo di criterio che può essere inserito in /public è più limitato. Considerala l'API dei criteri esportata della piattaforma: tutto ciò che riguarda l'interfaccia tra /system e /vendor appartiene a questa sezione.
  • system/sepolicy/private. Sono inclusi i criteri necessari per il funzionamento dell'immagine di sistema, ma i criteri relativi alle immagini del fornitore non devono essere presi in considerazione.
  • system/sepolicy/vendor. Include le norme per i componenti che vanno in /vendor, ma esistono nella struttura ad albero della piattaforma di base (non nelle directory specifiche del dispositivo). Si tratta di un artefatto della distinta tra dispositivi e componenti globali del sistema di compilazione. A livello concettuale, fa parte delle norme specifiche per i dispositivi descritte di seguito.
  • device/manufacturer/device-name/sepolicy. Include criteri specifici per i dispositivi. Sono incluse anche le personalizzazioni del dispositivo per le norme, che in Android 8.0 e versioni successive corrispondono alle norme per i componenti sull'immagine del fornitore.

In Android 11 e versioni successive, le partizioni system_ext e product possono includere anche criteri specifici per le partizioni. I criteri system_ext e product sono inoltre suddivisi in pubblici e privati e i fornitori possono utilizzare i criteri pubblici di system_ext e product, come i criteri di sistema.

  • SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS. Sono inclusi i criteri esportati per essere utilizzati nei criteri specifici del fornitore. Installato nella partizione system_ext.
  • SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS. Include i criteri necessari per il funzionamento dell'immagine system_ext, ma di cui i criteri dell'immagine del fornitore non devono essere a conoscenza. Installato nella partizione system_ext.
  • PRODUCT_PUBLIC_SEPOLICY_DIRS. Include il criterio esportato per l'utilizzo in criteri specifici del fornitore. Installato nella partizione del prodotto.
  • PRODUCT_PRIVATE_SEPOLICY_DIRS. Sono incluse le norme necessarie per il funzionamento dell'immagine del prodotto, ma le norme relative alle immagini del fornitore non devono essere prese in considerazione. Installato nella partizione del prodotto.
Nota:quando viene utilizzato GSI, le partizioni system_ext e product dell'OEM non vengono montate. Le regole nel sepolicy del fornitore che utilizza system_ext e il criterio pubblico del prodotto dell'OEM diventano NOP perché mancano le definizioni del tipo specifico per OEM.
Nota: fai molta attenzione quando utilizzi le norme pubbliche system_ext e del prodotto. I criteri pubblici fungono da API esportate tra system_ext/product e il fornitore. I partner sono tenuti a gestire autonomamente i problemi di compatibilità.

Scenari di criteri supportati

Sui dispositivi lanciati con Android 8.0 e versioni successive, l'immagine del fornitore deve funzionare con l'immagine di sistema OEM e l'immagine di sistema AOSP di riferimento fornite da Google (e superare il CTS su questa immagine di riferimento). Questi requisiti garantiscono una separazione chiara tra il framework e il codice del fornitore. Questi dispositivi supportano i seguenti scenari.

estensioni solo immagini del fornitore

Esempio: aggiunta di un nuovo servizio a vndservicemanager dall'immagine del fornitore che supporta i processi dell'immagine del fornitore.

Come per i dispositivi lanciati con versioni precedenti di Android, aggiungi la personalizzazione specifica del dispositivo in device/manufacturer/device-name/sepolicy. Le nuove norme che regolano il modo in cui i componenti del fornitore interagiscono con (solo) altri componenti del fornitore devono coinvolgere tipi presenti solo in device/manufacturer/device-name/sepolicy. Le norme scritte qui consentono il funzionamento del codice del fornitore, non verranno aggiornate nell'ambito di un aggiornamento OTA solo del framework e sono presenti nelle norme combinate su un dispositivo con l'immagine di sistema AOSP di riferimento.

supporto immagini del fornitore per lavorare con AOSP

Esempio: aggiunta di un nuovo processo (registrato con hwservicemanager dall'immagine del fornitore) che implementa un HAL definito da AOSP.

Come per i dispositivi lanciati con versioni precedenti di Android, esegui la personalizzazione specifica del dispositivo in device/manufacturer/device-name/sepolicy. Il criterio esportato nell'ambito di system/sepolicy/public/ è disponibile per l'utilizzo e viene fornito nell'ambito delle norme del fornitore. I tipi e gli attributi delle norme pubbliche possono essere utilizzati nelle nuove regole che definiscono le interazioni con i nuovi bit specifici del fornitore, rispettando le limitazioni neverallowfornite. Come nel caso del solo fornitore, i nuovi criteri in questo caso non verranno aggiornati nell'ambito di un'agenzia di viaggi online esclusiva ed è presente nei criteri combinati su un dispositivo con l'immagine di sistema AOSP di riferimento.

Estensioni solo per immagini di sistema

Esempio: aggiunta di un nuovo servizio (registrato con servicemanager) a cui accedono solo altri processi dall'immagine di sistema.

Aggiungi questo criterio a system/sepolicy/private. Puoi aggiungere ulteriori processi o oggetti per abilitare la funzionalità in un'immagine di sistema del partner, a condizione che questi nuovi bit non debbano interagire con i nuovi componenti dell'immagine del fornitore (in particolare, questi processi o oggetti devono funzionare completamente senza il criterio dell'immagine del fornitore). Il criterio esportato da system/sepolicy/public è disponibile qui, così come per le estensioni solo con immagine del fornitore. Questo criterio fa parte dell'immagine di sistema e potrebbe essere aggiornato in un'OTA solo del framework, ma non sarà presente quando si utilizza l'immagine di sistema AOSP di riferimento.

Estensioni vendor-image che forniscono componenti AOSP estesi

Esempio: un nuovo HAL non AOSP da utilizzare da parte di client estesi che esiste anche nell'immagine di sistema AOSP (ad esempio un system_server esteso).

I criteri per l'interazione tra il sistema e il fornitore devono essere inclusi nella directory device/manufacturer/device-name/sepolicy fornita nella partizione del fornitore. È simile allo scenario precedente di aggiunta del supporto delle immagini del fornitore per il funzionamento con l'immagine AOSP di riferimento, tranne per il fatto che i componenti AOSP modificati potrebbero anche richiedere criteri aggiuntivi per funzionare correttamente con il resto della partizione di sistema (il che va bene purché abbiano ancora le etichette di tipo AOSP pubblico).

Le norme per l'interazione dei componenti AOSP pubblici con le estensioni solo per l'immagine di sistema devono essere in system/sepolicy/private.

Estensioni dell'immagine di sistema che accedono solo alle interfacce AOSP

Esempio: un nuovo processo di sistema non AOSP deve accedere a un HAL su cui si basa AOSP.

È simile all'esempio di estensione solo immagine del sistema, tranne per il fatto che i nuovi componenti di sistema possono interagire tramite l'interfacciasystem/vendor. I criteri per il nuovo componente di sistema devono essere inseriti in system/sepolicy/private, il che è accettabile a condizione che vengano utilizzati tramite un'interfaccia già stabilita da AOSP in system/sepolicy/public (ovvero che siano presenti i tipi e gli attributi richiesti per la funzionalità). Sebbene i criteri possano essere inclusi nei criteri specifici del dispositivo, non sarà possibile utilizzare altri tipi di system/sepolicy/private o modificarli (in alcun modo che influisca sui criteri) a seguito di un aggiornamento solo del framework. Il criterio può essere modificato in un'OTA solo del framework, ma non sarà presente se si utilizza un'immagine di sistema AOSP (che non avrà nemmeno il nuovo componente di sistema).

estensioni immagine del fornitore che pubblicano nuovi componenti di sistema

Esempio: aggiunta di un nuovo HAL non AOSP da utilizzare da parte di un processo client senza un analogo AOSP (e quindi richiede un proprio dominio).

Come nell'esempio di estensioni AOSP, le norme per le interazioni tra il sistema e il fornitore devono essere inserite nella directory device/manufacturer/device-name/sepolicy fornita nella partizione del fornitore (per garantire che le norme di sistema non siano a conoscenza di dettagli specifici del fornitore). Puoi aggiungere nuovi tipi pubblici che estendono il criterio in system/sepolicy/public; questa operazione deve essere eseguita solo in aggiunta al criterio AOSP esistente, ovvero non rimuovere il criterio pubblico AOSP. I nuovi tipi pubblici possono quindi essere utilizzati per i criteri in system/sepolicy/private e in device/manufacturer/device-name/sepolicy.

Tieni presente che ogni aggiunta a system/sepolicy/public aggiunge complessità mostrando una nuova garanzia di compatibilità che deve essere monitorata in un file di mappatura ed è soggetta ad altre limitazioni. Solo i nuovi tipi e le regole di autorizzazione corrispondenti possono essere aggiunti in system/sepolicy/public; gli attributi e altre istruzioni relative ai criteri non sono supportati. Inoltre, i nuovi tipi pubblici non possono essere utilizzati per etichettare direttamente gli oggetti nel criterio /vendor.

Scenari di criteri non supportati

I dispositivi lanciati con Android 8.0 e versioni successive non supportano lo scenario e gli esempi di norme riportati di seguito.

Estensioni aggiuntive all'immagine di sistema che richiedono l'autorizzazione per i nuovi componenti dell'immagine del fornitore dopo un aggiornamento OTA solo del framework

Esempio: nella prossima release di Android viene aggiunto un nuovo processo di sistema non AOSP che richiede un proprio dominio e deve accedere a un nuovo HAL non AOSP.

Simile all'interazione di nuovi componenti di sistema e fornitori (non AOSP), tranne per il fatto che il nuovo tipo di sistema è stato introdotto in un'agenzia di viaggi online basata solo sul framework. Sebbene il nuovo tipo possa essere aggiunto al criterio in system/sepolicy/public, il criterio del fornitore esistente non è a conoscenza del nuovo tipo in quanto monitora solo le norme pubbliche del sistema Android 8.0. AOSP gestisce questo problema esponendo le risorse fornite dal fornitore tramite un attributo (ad esempio, l'attributo hal_foo), ma poiché le estensioni dei partner di attributo non sono supportate in system/sepolicy/public, questo metodo non è disponibile per i criteri del fornitore. L'accesso deve essere fornito da un tipo pubblico esistente in precedenza.

Esempio: una modifica a un processo di sistema (AOSP o non AOSP) deve cambiare il modo in cui interagisce con il nuovo componente del fornitore non AOSP.

I criteri nell'immagine di sistema devono essere scritti senza conoscenza di personalizzazioni specifiche del fornitore. I criteri relativi a interfacce specifiche in AOSP vengono quindi esposti tramite attributi in system/sepolicy/public, in modo che i criteri del fornitore possano attivare i futuri criteri di sistema che utilizzano questi attributi. Tuttavia, le estensioni degli attributi in system/sepolicy/public non sono supportate, quindi tutti i criteri che determinano il modo in cui i componenti del sistema interagiscono con i nuovi componenti del fornitore (e che non è gestito dagli attributi già presenti in AOSP system/sepolicy/public) devono essere in device/manufacturer/device-name/sepolicy. Ciò significa che i tipi di sistema non possono modificare l'accesso consentito ai tipi di fornitori nell'ambito di un aggiornamento OTA solo del framework.