Consulta questa pagina per familiarizzare con i concetti di SELinux.
Controllo dell'accesso obbligatorio
Security Enhanced Linux (SELinux) è un sistema di controllo dell'accesso obbligatorio (MAC) per il sistema operativo Linux. In quanto sistema MAC, è diverso dal familiare sistema di controllo dell'accesso discrezionale (DAC) di Linux. In un sistema DAC esiste un concetto di proprietà, in base al quale un proprietario di una determinata risorsa controlla le autorizzazioni di accesso associate. In genere, questo tipo di accesso è granulare e soggetto a un'escalation involontaria dei privilegi. Un sistema MAC, invece, consulta un'autorità centralizzata per prendere una decisione su tutti i tentativi di accesso.
SELinux è stato implementato nell'ambito del framework Linux Security Module (LSM), che riconosce vari oggetti del kernel e azioni sensibili eseguite su di essi. Nel punto in cui ciascuna di queste azioni verrà eseguita, viene chiamata una funzione di hook LSM per determinare se l'azione deve essere consentita o meno in base alle informazioni memorizzate in un oggetto di sicurezza opaco. SELinux fornisce un'implementazione per questi hook e la gestione di questi oggetti di sicurezza, che si combinano con i propri criteri per determinare le decisioni di accesso.
Insieme ad altre misure di sicurezza di Android, i criteri di controllo dell'accesso di Android limitano notevolmente i potenziali danni causati da macchine e account compromessi. L'utilizzo di strumenti come i controlli di accesso facoltativi e obbligatori di Android ti offre una struttura per garantire che il software venga eseguito solo al livello di privilegio minimo. In questo modo si riducono gli effetti degli attacchi e la probabilità che i processi errati sovrascrivano o addirittura trasmettano dati.
In Android 4.3 e versioni successive, SELinux fornisce un controllo dell'accesso obbligatorio (MAC) in tutti gli ambienti di controllo dell'accesso discrezionale (DAC) tradizionali. Ad esempio, in genere il software deve essere eseguito come account utente root per scrivere su dispositivi di blocco non elaborati. In un ambiente Linux tradizionale basato su DAC, se l'utente root viene compromesso, può scrivere su ogni dispositivo di blocco non elaborato. Tuttavia, SELinux può essere utilizzato per etichettare questi dispositivi in modo che il processo a cui è stato assegnato il privilegio dell'utente root possa scrivere solo in quelli specificati nel criterio associato. In questo modo, il processo non può sovrascrivere i dati e le impostazioni di sistema al di fuori del dispositivo di blocco raw specifico.
Consulta la sezione Casi d'uso per altri esempi di minacce e modi per gestirle con SELinux.
Livelli di applicazione
SELinux può essere implementato in diverse modalità:
- Permissive: il criterio di sicurezza SELinux non viene applicato, ma solo registrato.
- Applicazione: il criterio di sicurezza viene applicato e registrato. I fallimenti vengono visualizzati come errori EPERM.
Questa scelta è binaria e determina se il criterio interviene o se consente semplicemente di raccogliere potenziali errori. Il valore Permissive è particolarmente utile durante l'implementazione.
Tipi, attributi e regole
Android si basa sul componente di applicazione del tipo (TE) di SELinux per le sue norme. Ciò significa che a tutti gli oggetti (ad esempio file, processi o socket) è associato un
tipo. Ad esempio, per impostazione predefinita, un'app
ha il tipo untrusted_app
. Per un processo, il tipo è noto anche come dominio. È possibile annotare un tipo con uno o più attributi. Gli attributi sono utili per fare riferimento a più tipi contemporaneamente.
Gli oggetti vengono mappati a classi (ad esempio un file, una directory, un link simbolico, una presa di corrente) e i diversi tipi di accesso per ogni classe sono rappresentati dalle autorizzazioni.
Ad esempio, l'autorizzazione open
esiste per la classe
file
. Sebbene i tipi e gli attributi vengano aggiornati regolarmente nell'ambito del criterio SELinux di Android, le autorizzazioni e le classi sono definite in modo statico e raramente aggiornate nell'ambito di una nuova release di Linux.
Una regola del criterio ha il seguente formato:
allow source target:class permissions;
dove:
- Origine: il tipo (o attributo) dell'oggetto della regola. Chi richiede l'accesso?
- Target: il tipo (o attributo) dell'oggetto. A cosa si riferisce l'accesso richiesto?
- Classe: il tipo di oggetto (ad esempio file, socket) a cui viene eseguito l'accesso.
- Autorizzazioni: l'operazione (o l'insieme di operazioni) (ad esempio, lettura, scrittura) eseguita.
Un esempio di regola è:
allow untrusted_app app_data_file:file { read write };
Ciò significa che le app sono autorizzate a leggere e scrivere file etichettati comeapp_data_file
. Esistono altri tipi di app. Ad esempio, isolated_app
viene utilizzato per i servizi per app con isolatedProcess=true
nel file manifest. Anziché ripetere la regola per entrambi i tipi, Android utilizza un attributo denominato appdomain
per tutti i tipi che coprono le app:
# Associate the attribute appdomain with the type untrusted_app. typeattribute untrusted_app appdomain; # Associate the attribute appdomain with the type isolated_app. typeattribute isolated_app appdomain; allow appdomain app_data_file:file { read write };
Quando viene scritta una regola che specifica un nome di attributo, questo viene visualizzato automaticamente nell'elenco dei domini o dei tipi associati all'attributo. Ecco alcuni attributi importanti:
domain
: attributo associato a tutti i tipi di processo,file_type
: attributo associato a tutti i tipi di file.
Macro
Per l'accesso ai file in particolare, esistono molti tipi di autorizzazioni da prendere in considerazione. Ad esempio, l'autorizzazione read
non è sufficiente per aprire il
file o chiamare stat
. Per semplificare la definizione delle regole, Android fornisce un insieme di macro per gestire i casi più comuni. Ad esempio, per includere le autorizzazioni mancanti come open
, la regola riportata sopra potrebbe essere riscritta come segue:
allow appdomain app_data_file:file rw_file_perms;
Consulta i file global_macros
e te_macros
per altri esempi di macro utili. Le macro devono essere utilizzate, se possibile, per contribuire a ridurre la probabilità di errori dovuti a rifiuti delle autorizzazioni correlate.
Una volta definito, un tipo deve essere associato al file o al processo che rappresenta. Per ulteriori dettagli su come viene eseguita questa associazione, consulta Implementazione di SELinux. Per ulteriori informazioni sulle regole, consulta il notebook SELinux.
Contesto e categorie di sicurezza
Quando esegui il debug dei criteri SELinux o etichetti i file (utilizzando file_contexts
o quando esegui ls -Z
), potresti imbatterti in un contesto di sicurezza (noto anche come etichetta). Ad
esempio:
u:r:untrusted_app:s0:c15,c256,c513,c768
. Un contesto di sicurezza ha il formato:
user:role:type:sensitivity[:categories]
. In genere puoi ignorare i campi user
, role
e sensitivity
di un contesto (vedi Specificità). Il campo type
è spiegato nella sezione precedente. categories
fanno parte del supporto della sicurezza a più livelli (MLS) in SELinux. In Android 12 e versioni successive, le categorie vengono utilizzate per:
- Isolare i dati dell'app dall'accesso da parte di un'altra app,
- Isolare i dati dell'app da un utente fisico all'altro.
Specificità
Android non utilizza tutte le funzionalità fornite da SELinux. Quando leggi la documentazione esterna, tieni presente quanto segue:
- La maggior parte dei criteri in AOSP è definita utilizzando il Kernel Policy Language. Esistono alcune eccezioni per l'utilizzo del linguaggio intermedio comune (CIL).
- Gli utenti SELinux non vengono utilizzati. L'unico utente definito è
u
. Se necessario, gli utenti fisici vengono rappresentati utilizzando il campo categorie di un contesto di sicurezza. - I ruoli SELinux e il controllo degli accessi basato su ruoli (RBAC) non vengono utilizzati. Vengono definiti e utilizzati due ruoli predefiniti:
r
per i soggetti eobject_r
per gli oggetti. - Le sensibilità SELinux non vengono utilizzate. La sensibilità predefinita
s0
è sempre impostata. - I valori booleani SELinux non vengono utilizzati. Quando il criterio viene creato per un dispositivo, non dipende dallo stato del dispositivo. In questo modo, il controllo e il debug dei criteri sono più semplici.