Il processo init dispone di autorizzazioni quasi illimitate e utilizza script di input dalle partizioni di sistema e del fornitore per inizializzare il sistema durante il processo di avvio. Questo accesso causa un'enorme lacuna nella suddivisione sistema/fornitore di Treble, in quanto 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) stabile del fornitore del sistema.
Vendor init è progettato per colmare questa lacuna utilizzando un dominio
Linux (SELinux) con sicurezza avanzata vendor_init
per eseguire
i comandi presenti in /vendor
con autorizzazioni specifiche del fornitore.
Meccanismo
Vendor init crea un 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
molte meno autorizzazioni rispetto al contesto init predefinito e il suo accesso è
limitato a file, proprietà e così via specifici del fornitore o parte
dell'ABI stabile del fornitore del sistema.
Init controlla ogni script che carica per verificare se il relativo percorso inizia con /vendor
e, in caso affermativo, lo tagga con un'indicazione che i relativi comandi devono essere eseguiti nel contesto di inizializzazione del fornitore. Ogni comando integrato 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 sono annotati per essere eseguiti nel sottoprocesso di inizializzazione del fornitore e sono quindi soggetti alla SEPolicy di inizializzazione del fornitore.
- La maggior parte dei comandi che influiscono sullo stato di inizializzazione interno (ad es. avvio e interruzione dei servizi) viene eseguita all'interno del normale processo di inizializzazione. Questi comandi sono consapevoli che uno script del fornitore li chiama per gestire le proprie autorizzazioni non SELinux.
Il ciclo 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, questo comando viene inviato tramite la comunicazione interprocesso (IPC) al sottoprocesso init del fornitore, che esegue il comando e invia il risultato a init.
Utilizzare vendor_init
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 solo di sistema.
Tuttavia, se i comandi in un determinato script del fornitore violano le limitazioni di inizializzazione del fornitore, non vengono eseguiti. I comandi non riusciti hanno una riga nel log del kernel (visibile con dmesg) da init che indica l'errore. Un controllo SELinux accompagna qualsiasi comando non riuscito a causa del criterio SELinux. Esempio di 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 prevista (ad esempio se accede a un file o a una proprietà di sistema), deve essere reimplementato in modo compatibile con Treble, passando solo attraverso interfacce stabili. Le regole Neverallow impediscono l'aggiunta di autorizzazioni per accedere ai file di sistema che non fanno parte dell'ABI stabile del fornitore del sistema.
- Se l'etichetta SELinux è nuova e non sono già state concesse autorizzazioni nel
vendor_init.te
di sistema né escluse autorizzazioni 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 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 sottoprocesso
init del fornitore.
SEPolicy per vendor_init è suddivisa tra le directory private (system/sepolicy/private/vendor_init.te) e pubbliche (system/sepolicy/public/vendor_init.te) in system/sepolicy.