Personalizzazione di SELinux

Dopo aver integrato il livello base della funzionalità SELinux e analizzato attentamente i risultati, puoi aggiungere le tue impostazioni dei criteri per coprire le tue personalizzazioni al 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 dovrebbero rimuovere la politica SELinux esistente. Altrimenti rischiano di compromettere l'implementazione di Android SELinux e le applicazioni che governa. Ciò include applicazioni di terze parti che probabilmente dovranno essere migliorate per essere conformi e operative. Le applicazioni non devono richiedere alcuna modifica per continuare a funzionare sui dispositivi abilitati SELinux.

Quando inizi a personalizzare SELinux, ricorda di:

  • Scrivi la policy SELinux per tutti i nuovi demoni
  • Utilizza domini predefiniti quando appropriato
  • Assegna un dominio a qualsiasi processo generato come servizio init
  • Acquisire familiarità con le macro prima di scrivere la policy
  • Invia le modifiche alla policy principale ad AOSP

E ricorda di non:

  • Crea policy incompatibile
  • Consenti la personalizzazione dei criteri dell'utente finale
  • Consenti personalizzazioni dei criteri MDM
  • Spaventare gli utenti con violazioni delle norme
  • Aggiungi backdoor

Consulta la sezione Funzionalità di sicurezza del kernel del documento Definizione di compatibilità Android per requisiti specifici.

SELinux utilizza un approccio whitelist, il che significa che tutti gli accessi devono essere esplicitamente consentiti nella policy per essere concessi. Poiché la policy SELinux predefinita di Android supporta già il progetto Android Open Source, non è necessario modificare in alcun modo le impostazioni di SELinux. Se personalizzi le impostazioni di SELinux, fai molta attenzione a non danneggiare le applicazioni esistenti. Per iniziare:

  1. Utilizza l' ultimo kernel Android .
  2. Adottare il principio del privilegio minimo .
  3. Risolvi solo le tue aggiunte ad Android. La policy predefinita funziona automaticamente con la codebase del progetto Android Open Source .
  4. Compartimentalizzare i componenti software in moduli che svolgono compiti singolari.
  5. Crea policy SELinux che isolano tali attività da funzioni non correlate.
  6. Inserisci tali policy nei file *.te (l'estensione per i file sorgente delle policy SELinux) all'interno della directory /device/ manufacturer / device-name /sepolicy e utilizza le variabili BOARD_SEPOLICY per includerle nella tua build.
  7. Rendi inizialmente permissivi i nuovi domini. Questo viene fatto utilizzando una dichiarazione permissiva nel file .te del dominio.
  8. Analizza i risultati e perfeziona le definizioni del tuo dominio.
  9. Rimuovere la dichiarazione permissiva quando non compaiono ulteriori rifiuti nelle build di userdebug.

Dopo aver integrato la modifica della policy 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, la politica di SELinux cambia solo quando cambia il modello del software e non l'effettiva implementazione.

Quando inizi a personalizzare SELinux, controlla prima le tue aggiunte ad Android. Se hai aggiunto un componente che svolge 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 non necessari, è meglio essere troppo ampi e compatibili piuttosto che troppo restrittivi e incompatibili, il che si traduce in funzioni del dispositivo interrotte. Al contrario, se le tue modifiche andranno a beneficio di altri, dovresti inviare le modifiche alla policy SELinux predefinita come patch . Se la patch viene applicata ai criteri di sicurezza predefiniti, non sarà necessario apportare questa modifica a ogni nuova versione di Android.

Esempi di dichiarazioni politiche

SELinux si basa sul linguaggio informatico M4 e quindi supporta una varietà di macro per risparmiare tempo.

Nell'esempio seguente, a tutti i domini viene concesso l'accesso in lettura o scrittura su /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 };

Questa stessa istruzione può essere scritta con le macro SELinux *_file_perms (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;

Politica di esempio

Ecco una policy di esempio completa per DHCP, che esamineremo di seguito:

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 dalla politica di sicurezza di base ( domain ). Dagli esempi di istruzioni precedenti, DHCP può leggere e scrivere su /dev/null .

Nella seconda riga DHCP viene identificato come dominio permissivo.

Nella riga init_daemon_domain(dhcp) , la policy afferma che DHCP viene generato da init ed è autorizzato a comunicare con esso.

Nella riga net_domain(dhcp) , la policy consente a DHCP di utilizzare funzionalità di rete comuni dal dominio net come leggere e scrivere pacchetti TCP, comunicare su socket e condurre richieste DNS.

Nella riga allow dhcp proc_net:file write; , la policy afferma che DHCP può scrivere su file specifici in /proc . Questa riga dimostra l'etichettatura dei file a grana fine di SELinux. Utilizza l'etichetta proc_net per limitare l'accesso in scrittura solo ai file in /proc/sys/net .

Il blocco finale dell'esempio che inizia allow dhcp netd:fd use; descrive come è possibile consentire alle applicazioni di interagire tra loro. La policy afferma che DHCP e netd possono comunicare tra loro tramite descrittori di file, file FIFO, socket di datagramma e socket di flusso UNIX. DHCP può solo leggere e scrivere dai socket di datagramma e dai socket di flusso UNIX e non crearli o aprirli.

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
processi
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
capacità
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

DI PIÙ

E ALTRO

non permettere mai regole

Le regole neverallow di SELinux proibiscono comportamenti che non dovrebbero mai verificarsi. Con i test di compatibilità , le regole neverallow di SELinux vengono ora applicate su tutti i dispositivi.

Le seguenti linee guida hanno lo scopo di aiutare i produttori a evitare errori relativi alle regole neverallow durante la personalizzazione. I numeri delle regole qui utilizzati corrispondono ad Android 5.1 e sono soggetti a modifiche in base al rilascio.

Regola 48: neverallow { domain -debuggerd -vold -dumpstate -system_server } self:capability sys_ptrace;
Vedi la pagina man di ptrace . La funzionalità sys_ptrace garantisce la possibilità di ptrace qualsiasi processo, il che consente un grande controllo su altri processi e dovrebbe appartenere solo a componenti di sistema designati, delineati nella regola. La necessità di questa funzionalità spesso indica la presenza di qualcosa che non è destinato a build rivolte agli utenti o funzionalità che non sono necessarie. Rimuovere 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, si 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 riscontra un problema con questa regola neverallow è spostare il codice incriminato nella partizione /system .

Personalizzazione di SEPolicy in Android 8.0+

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

Posizionamento politico

In Android 7.0 e versioni precedenti, i produttori di dispositivi potevano aggiungere criteri a BOARD_SEPOLICY_DIRS , inclusi criteri destinati ad aumentare i criteri AOSP su diversi tipi di dispositivi. In Android 8.0 e versioni successive, l'aggiunta di una policy a BOARD_SEPOLICY_DIRS inserisce la policy solo nell'immagine del fornitore.

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

  • sistema/politica/pubblico . Include la policy esportata per l'utilizzo nella policy specifica del fornitore. Tutto rientra nell'infrastruttura di compatibilità Android 8.0. La politica pubblica è pensata per persistere tra le versioni in modo da poter includere qualsiasi cosa /public nella tua politica personalizzata. Per questo motivo, il tipo di policy che può essere inserita in /public è più limitato. Considera questa l'API della policy esportata dalla piattaforma: tutto ciò che riguarda l'interfaccia tra /system e /vendor appartiene qui.
  • sistema/sepolicy/privato . Include la politica necessaria per il funzionamento dell'immagine del sistema, ma di cui la politica dell'immagine del fornitore non dovrebbe essere a conoscenza.
  • sistema/politica/fornitore . Include la policy per i componenti che vanno in /vendor ma esistono nell'albero della piattaforma principale (non nelle directory specifiche del dispositivo). Questo è un artefatto della distinzione del sistema di build tra dispositivi e componenti globali; concettualmente questa è una parte della politica specifica del dispositivo descritta di seguito.
  • dispositivo/ manufacturer / device-name /sepolicy . Include policy specifiche per il dispositivo. Include anche la personalizzazione del dispositivo rispetto ai criteri, che in Android 8.0 e versioni successive corrisponde ai criteri per i componenti nell'immagine del fornitore.

In Android 11 e versioni successive, le partizioni system_ext e product possono includere anche policy specifiche della partizione. Anche le policy system_ext e del prodotto sono suddivise in pubbliche e private e i fornitori possono utilizzare le policy pubbliche di system_ext e del prodotto, come la policy di sistema.

  • SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS . Include la policy esportata per l'utilizzo nella policy specifica del fornitore. Installato nella partizione system_ext.
  • SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS . Include la policy necessaria per il funzionamento dell'immagine system_ext, ma di cui la policy dell'immagine del fornitore non dovrebbe essere a conoscenza. Installato nella partizione system_ext.
  • PRODUCT_PUBLIC_SEPOLICY_DIRS . Include la policy esportata per l'utilizzo nella policy specifica del fornitore. Installato nella partizione del prodotto.
  • PRODUCT_PRIVATE_SEPOLICY_DIRS . Include la politica necessaria per il funzionamento dell'immagine del prodotto, ma di cui la politica dell'immagine del fornitore non dovrebbe essere a conoscenza. Installato nella partizione del prodotto.
Nota: quando si utilizza GSI, le partizioni system_ext e prodotto dell'OEM non verranno montate. Le regole nella policy del fornitore che utilizzano system_ext dell'OEM e la policy pubblica del prodotto diventano NOP perché mancano le definizioni di tipo specifiche dell'OEM.
Nota: prestare particolare attenzione quando si utilizzano system_ext e le policy pubbliche del prodotto. Le politiche pubbliche fungono da API esportate tra system_ext/product e fornitore. I partner dovrebbero gestire autonomamente i problemi di compatibilità.

Scenari politici supportati

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

estensioni solo per le immagini del fornitore

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

Come per i dispositivi lanciati con versioni Android precedenti, aggiungi la personalizzazione specifica del dispositivo in device/ manufacturer / device-name /sepolicy . La nuova policy che regola il modo in cui i componenti del fornitore interagiscono con (solo) altri componenti del fornitore dovrebbe coinvolgere i tipi presenti solo in device/ manufacturer / device-name /sepolicy . La policy scritta qui consente il funzionamento del codice del fornitore, non verrà aggiornata come parte di un'OTA solo framework e sarà presente nella policy combinata su un dispositivo con l'immagine del sistema AOSP di riferimento.

supporto dell'immagine del fornitore per funzionare 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 avviati con versioni Android precedenti, esegui la personalizzazione specifica del dispositivo in device/ manufacturer / device-name /sepolicy . La policy esportata come parte di system/sepolicy/public/ è disponibile per l'uso e viene spedita come parte della policy del fornitore. I tipi e gli attributi della politica pubblica possono essere utilizzati in nuove regole che dettano le interazioni con i nuovi bit specifici del fornitore, soggette alle restrizioni neverallow fornite. Come nel caso del solo fornitore, la nuova policy qui non verrà aggiornata come parte di un'OTA basata solo sul framework e sarà presente nella policy combinata su un dispositivo con l'immagine del 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 questa policy a system/sepolicy/private . È possibile aggiungere processi o oggetti aggiuntivi per abilitare la funzionalità in un'immagine del sistema partner, a condizione che questi nuovi bit non debbano interagire con nuovi componenti sull'immagine del fornitore (nello specifico, tali processi o oggetti devono funzionare completamente senza policy dell'immagine del fornitore) . La policy esportata da system/sepolicy/public è disponibile qui proprio come lo è per le estensioni solo per l'immagine del fornitore. Questa policy fa parte dell'immagine di sistema e potrebbe essere aggiornata in un'OTA solo framework, ma non sarà presente quando si utilizza l'immagine di sistema AOSP di riferimento.

estensioni dell'immagine del fornitore che servono componenti AOSP estesi

Esempio: un nuovo HAL non AOSP da utilizzare da client estesi che esistono anche nell'immagine del sistema AOSP (come un system_server esteso).

La policy per l'interazione tra il sistema e il fornitore deve essere inclusa nella directory device/ manufacturer / device-name /sepolicy fornita nella partizione del fornitore. Questo è simile allo scenario precedente in cui si aggiunge il supporto dell'immagine del fornitore per funzionare con l'immagine AOSP di riferimento, tranne per il fatto che i componenti AOSP modificati potrebbero anche richiedere policy aggiuntive per funzionare correttamente con il resto della partizione di sistema (il che va bene purché siano ancora avere le etichette di tipo AOSP pubbliche).

La politica per l'interazione dei componenti AOSP pubblici con le estensioni di sole immagini di sistema dovrebbe 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.

Questo è simile all'esempio dell'estensione della sola immagine del sistema , tranne per il fatto che i nuovi componenti del sistema possono interagire attraverso l'interfaccia system/vendor . La policy per il nuovo componente di sistema deve andare in system/sepolicy/private , il che è accettabile a condizione che avvenga attraverso un'interfaccia già stabilita da AOSP in system/sepolicy/public (ovvero che siano presenti i tipi e gli attributi richiesti per la funzionalità). Anche se la policy potrebbe essere inclusa nella policy specifica del dispositivo, non sarebbe in grado di utilizzare altri tipi system/sepolicy/private ​​o di apportare modifiche (in alcun modo che influenzi la policy) come risultato di un aggiornamento del solo framework. La policy può essere modificata in un'OTA solo framework, ma non sarà presente quando si utilizza un'immagine di sistema AOSP (che non avrà nemmeno il nuovo componente di sistema).

estensioni dell'immagine del fornitore che servono 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 il proprio dominio).

Similmente all'esempio delle estensioni AOSP , la policy per le interazioni tra il sistema e il fornitore deve essere inserita nella directory device/ manufacturer / device-name /sepolicy fornita nella partizione del fornitore (per garantire che la policy di sistema non sia a conoscenza dei dettagli specifici del fornitore). È possibile aggiungere nuovi tipi pubblici che estendono la policy in system/sepolicy/public ; ciò dovrebbe essere fatto solo in aggiunta alla politica AOSP esistente, vale a dire non eliminare la politica pubblica AOSP. I nuovi tipi pubblici possono quindi essere utilizzati per la policy in system/sepolicy/private e in device/ manufacturer / device-name /sepolicy .

Tieni presente che ogni aggiunta a system/sepolicy/public aggiunge complessità esponendo una nuova garanzia di compatibilità che deve essere tracciata in un file di mappatura e che è soggetta ad altre restrizioni. Solo nuovi tipi e le corrispondenti regole di autorizzazione possono essere aggiunti in system/sepolicy/public ; gli attributi e altre dichiarazioni di policy non sono supportati. Inoltre, i nuovi tipi pubblici non possono essere utilizzati per etichettare direttamente gli oggetti nella policy /vendor .

Scenari politici non supportati

I dispositivi avviati con Android 8.0 e versioni successive non supportano lo scenario e gli esempi di criteri seguenti.

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

Esempio: un nuovo processo di sistema non AOSP, che richiede un proprio dominio, viene aggiunto nella prossima versione di Android e necessita dell'accesso a un nuovo HAL non AOSP.

Simile all'interazione tra il nuovo sistema (non AOSP) e i componenti del fornitore , tranne per il fatto che il nuovo tipo di sistema viene introdotto in un'OTA solo framework. Sebbene il nuovo tipo possa essere aggiunto alla policy in system/sepolicy/public , la policy del fornitore esistente non è a conoscenza del nuovo tipo poiché tiene traccia solo della policy pubblica del sistema Android 8.0. AOSP gestisce questa situazione esponendo le risorse fornite dal fornitore tramite un attributo (ad esempio l'attributo hal_foo ) ma poiché le estensioni del partner dell'attributo non sono supportate in system/sepolicy/public , questo metodo non è disponibile per la policy del fornitore. L'accesso deve essere fornito da un tipo pubblico già esistente.

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

La policy sull'immagine di sistema deve essere scritta senza conoscere le personalizzazioni specifiche del fornitore. La politica relativa a interfacce specifiche in AOSP viene quindi esposta tramite attributi in system/sepolicy/public in modo che la politica del fornitore possa optare per la futura politica di sistema che utilizza questi attributi. Tuttavia, le estensioni degli attributi in system/sepolicy/public non sono supportate , quindi tutte le policy che stabiliscono come i componenti del sistema interagiscono con i nuovi componenti del fornitore (e che non sono gestite 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 come parte di un'OTA basata esclusivamente sul framework.