Il processo init ha autorizzazioni quasi illimitate e utilizza script di input sia dalle partizioni di sistema sia da quelle del fornitore per inizializzare il sistema durante il processo di avvio. Questo accesso causa un'enorme falla nella suddivisione del sistema/del fornitore di Treble, poiché gli script del fornitore possono indicare a init di accedere a file, proprietà e così via che non fanno parte dell'interfaccia binaria dell'applicazione (ABI) del sistema-fornitore stabile.
Vendor init è progettato per chiudere questa falla utilizzando un dominio vendor_init
SELinux (Linux con funzionalità di sicurezza avanzate) separato per eseguire i comandi trovati in /vendor
con autorizzazioni specifiche del fornitore.
Meccanismo
Il comando init del fornitore esegue il fork di un sottoprocesso di init all'inizio del processo di avvio con il
contesto SELinux u:r:vendor_init:s0
. Questo contesto SELinux ha autorizzazioni notevolmente inferiori rispetto al contesto init predefinito e il suo accesso è limitato a file, proprietà e così via specifici del fornitore o che fanno parte dell'ABI del fornitore di sistema stabile.
Init controlla ogni script caricato per verificare se il relativo percorso inizia con /vendor
e, in questo caso, lo contrassegna con un'indicazione che indica che i relativi comandi devono essere eseguiti nel contesto di init del fornitore. Ogni comando integrato di init è annotato con un valore booleano che specifica se il comando deve essere eseguito o meno nel sottoprocesso init del fornitore:
- La maggior parte dei comandi che accedono al file system è annotata per essere eseguita nel subprocess init del fornitore e sono quindi soggette al SEPolicy di init del fornitore.
- La maggior parte dei comandi che influiscono sullo stato di init interno (ad es. l'avvio e l'arresto dei servizi) viene eseguita all'interno della normale procedura di init. A questi comandi viene comunicato che uno script del fornitore li sta chiamando per gestire le proprie autorizzazioni non SELinux.
Il loop di elaborazione principale di init contiene un controllo che, se un comando è annotato per essere eseguito nel sottoprocesso del fornitore e proviene da uno script del fornitore, il comando viene inviato tramite la comunicazione interprocessuale (IPC) al sottoprocesso init del fornitore, che esegue il comando e restituisce il risultato a init.
Utilizzare l'inizializzazione del fornitore
L'inizializzazione del fornitore è attivata per impostazione predefinita e le relative limitazioni si applicano a tutti gli script di inizializzazione
presenti nella partizione /vendor
. L'inizializzazione del fornitore deve essere trasparente per i fornitori i cui script non accedono già a file, proprietà e così via di sola proprietà del sistema.
Tuttavia, se i comandi in un determinato script del fornitore violano le limitazioni di inizializzazione del fornitore, i comandi non vengono eseguiti. I comandi che non vanno a buon fine hanno una riga nel log del kernel (visibile con dmesg) da init che indica l'errore. Un controllo SELinux accompagna qualsiasi comando con errore che non è riuscito a causa del criterio SELinux. Esempio di un errore che include un controllo SELinux:
type=1400 audit(1511821362.996:9): avc: denied { search } for pid=540 comm="init" name="nfc" dev="sda45" ino=1310721 scontext=u:r:vendor_init:s0 tcontext=u:object_r:nfc_data_file:s0 tclass=dir permissive=0 init: Command 'write /data/nfc/bad_file_access 1234' action=boot (/vendor/etc/init/hw/init.walleye.rc:422) took 2ms and failed: Unable to write to file '/data/nfc/bad_file_access': open() failed: Permission denied
Se un comando non va a buon fine, hai due opzioni:
- Se il comando non va a buon fine a causa di una limitazione intenzionale (ad esempio se accede a una proprietà o a un file di sistema), deve essere reimplementato in modo compatibile con Treble, utilizzando solo interfacce stabili. Le regole Neverallow impediscono di aggiungere autorizzazioni per accedere ai file di sistema che non fanno parte dell'ABI del fornitore di sistema stabile.
- Se l'etichetta SELinux è nuova e non sono già state concesse autorizzazioni nel
vendor_init.te
di sistema né autorizzazioni escluse tramite le regole neverallow, alla nuova etichetta potrebbero essere concesse autorizzazioni nelvendor_init.te
specifico del dispositivo.
Per i dispositivi lanciati prima di Android 9, le regole neverallows possono essere aggirate aggiungendo l'attributo type data_between_core_and_vendor_violators
al file vendor_init.te
specifico del dispositivo.
Posizioni del codice
La maggior parte della logica per l'IPC di inizializzazione del fornitore si trova in system/core/init/subcontext.cpp.
La tabella dei comandi si trova nella classe BuiltinFunctionMap
in system/core/init/builtins.cpp
e include annotazioni che indicano se il comando deve essere eseguito nel subprocess init del fornitore.
Il file SEPolicy per l'inizializzazione del fornitore è suddiviso nelle directory private (system/sepolicy/private/vendor_init.te) e pubbliche (system/sepolicy/public/vendor_init.te) in system/sepolicy.