Init de proveedor

El proceso de init tiene permisos casi sin restricciones y usa secuencias de comandos de entrada de las particiones del sistema y del proveedor para inicializar el sistema durante el proceso de arranque. Este acceso causa un gran agujero en la división del sistema/proveedor de Treble, ya que los secuencias de comandos del proveedor pueden indicarle a init que acceda a archivos, propiedades, etcétera, que no forman parte de la interfaz binaria de aplicaciones (ABI) estable del sistema-proveedor.

El init de proveedor está diseñado para cerrar esta brecha con un dominio de Linux mejorado para la seguridad (SELinux) vendor_init independiente para ejecutar comandos que se encuentran en /vendor con permisos específicos del proveedor.

Mecanismo

El init de 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 init predeterminado, y su acceso se limita a archivos, propiedades, etcétera, que son específicos del proveedor o forman parte de la ABI estable del sistema-proveedor.

Init verifica cada secuencia de comandos que carga para ver si su ruta comienza con /vendor y, si es así, la etiqueta con una indicación de que sus comandos se deben ejecutar en el contexto de init del proveedor. Cada compilación init está anotada con un valor booleano que especifica si el comando se debe ejecutar en el subproceso init del proveedor:

  • La mayoría de los comandos que acceden al sistema de archivos están anotados para ejecutarse en el subproceso de 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 se ejecutan con la información de que una secuencia de comandos del proveedor los llama para que realicen su propio control de permisos que no son de SELinux.

El bucle de procesamiento principal de init contiene una verificación que, si un comando está anotado 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 vendor init

La inicialización del proveedor está habilitada de forma predeterminada y sus restricciones se aplican a todas las secuencias de comandos de inicialización presentes en la partición /vendor. Vendor init debe ser transparente para los proveedores cuyos secuencias de comandos ya no acceden a archivos, propiedades, etc., solo del sistema.

Sin embargo, si los comandos de una secuencia de comandos del proveedor determinada infringen las restricciones de init del proveedor, los comandos fallarán. Los comandos que fallan tienen una línea en el registro del kernel (visible con dmesg) de init que indica la falla. Una auditoría de SELinux acompaña a cualquier comando que falló 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 falla un comando, tienes dos opciones:

  • Si el comando falla debido a una restricción prevista (por ejemplo, si el comando accede a un archivo o propiedad del sistema), se debe volver a implementar de una manera compatible con Treble, utilizando solo interfaces estables. Las reglas neverallow impiden agregar permisos para acceder a archivos del sistema que no forman parte de la ABI estable del sistema-proveedor.
  • Si la etiqueta de SELinux es nueva y aún no se le otorgaron permisos en el vendor_init.te del sistema ni se excluyeron permisos a través de las reglas de neverallow, es posible que se le otorguen permisos a la nueva etiqueta en el vendor_init.te específico del dispositivo.

En el caso de los dispositivos que se lanzan antes de Android 9, se pueden omitir las reglas de neverallow agregando el atributo de tipo 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 para el 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 contiene anotaciones que indican si el comando debe ejecutarse en el subproceso init del proveedor.

La SEPolicy para el init de proveedor se divide entre los directorios privados (system/sepolicy/private/vendor_init.te) y públicos (system/sepolicy/public/vendor_init.te) en system/sepolicy.