El proceso init tiene permisos casi ilimitados y usa secuencias de comandos de entrada de las particiones del sistema y del proveedor para inicializar el sistema durante el proceso de inicio. Este acceso causa un gran problema en la división del sistema y el proveedor de Treble, ya que las secuencias de comandos del proveedor pueden indicarle a init que acceda a archivos, propiedades, etc. que no forman parte de la interfaz binaria de aplicación (ABI) estable del sistema y el proveedor.
El init del proveedor está diseñado para cerrar este agujero mediante el uso de un dominio vendor_init
de Linux con seguridad mejorada (SELinux) independiente para ejecutar los comandos que se encuentran en /vendor
con permisos específicos del proveedor.
Mecanismo
El init del proveedor bifurca un subproceso de init al principio del proceso de inicio con el contexto de SELinux u:r:vendor_init:s0
. Este contexto de SELinux tiene muchos menos permisos que el contexto de init predeterminado y su acceso se limita a archivos, propiedades, etc., que son específicos del proveedor o que forman parte de la ABI estable del proveedor del sistema.
Init verifica cada secuencia de comandos que carga para ver si su ruta de acceso comienza con /vendor
y, de ser así, la etiqueta con una indicación de que sus comandos deben ejecutarse en el contexto de init del proveedor. Cada función integrada de init se anota con un valor booleano que especifica si el comando se debe ejecutar o no en el subproceso de init del proveedor:
- La mayoría de los comandos que acceden al sistema de archivos están anotados para ejecutarse en el subproceso init del proveedor y, por lo tanto, están sujetos a la SEPolicy de init del proveedor.
- La mayoría de los comandos que afectan el estado de init interno (p.ej., iniciar y detener servicios) se ejecutan dentro del proceso de init normal. Estos comandos saben que una secuencia de comandos del proveedor los llama para que realicen su propio control de permisos que no sean de SELinux.
El bucle de procesamiento principal de init contiene una verificación de que, si un comando tiene anotaciones para ejecutarse en el subproceso del proveedor y se origina en una secuencia de comandos del proveedor, ese comando se envía a través de la comunicación entre procesos (IPC) al subproceso init del proveedor, que ejecuta el comando y envía el resultado de vuelta a init.
Usa init de proveedor
El inicio del proveedor está habilitado de forma predeterminada, y sus restricciones se aplican a todas las secuencias de comandos de inicio presentes en la partición /vendor
. La inicialización del proveedor debe ser transparente para los proveedores cuyas secuencias de comandos ya no acceden a archivos, propiedades, etc. solo del sistema.
Sin embargo, si los comandos de una secuencia de comandos de proveedor determinada infringen las restricciones de inicialización del proveedor, los comandos fallan. Los comandos con errores tienen una línea en el registro del kernel (visible con dmesg) de init que indica el error. Una auditoría de SELinux acompaña a cualquier comando con errores que falle debido a la política de SELinux. Ejemplo de una falla que incluye una auditoría de 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
Si un comando falla, hay dos opciones:
- Si el comando falla debido a una restricción intencional (por ejemplo, si el comando accede a un archivo o propiedad del sistema), se debe volver a implementar de una manera compatible con Treble, pasando solo por interfaces estables. Las reglas Neverallow evitan que se agreguen permisos para acceder a los archivos del sistema que no forman parte de la ABI estable del proveedor del sistema.
- Si la etiqueta de SELinux es nueva y aún no se le otorgan permisos en el
vendor_init.te
del sistema ni se excluyen permisos a través de las reglas de neverallow, es posible que se le otorguen permisos a la etiqueta nueva en elvendor_init.te
específico del dispositivo.
En el caso de los dispositivos que se lanzan con versiones anteriores a Android 9, se pueden omitir las reglas de “Neverallow” agregando el tipo de atributo data_between_core_and_vendor_violators
al archivo vendor_init.te
específico del dispositivo.
Ubicaciones de código
La mayor parte de la lógica del IPC de init del proveedor se encuentra en system/core/init/subcontext.cpp.
La tabla de comandos se encuentra en la clase BuiltinFunctionMap
en system/core/init/builtins.cpp y, además, incluye anotaciones que indican si el comando debe ejecutarse en el subproceso de init del proveedor.
El SEPolicy para init del proveedor se divide en los directorios privado (system/sepolicy/private/vendor_init.te) y público (system/sepolicy/public/vendor_init.te) en system/sepolicy.