Compila la política de SELinux

En esta página, se explica cómo se compila la política de SELinux. La política de SELinux se compila a partir de la combinación de la política principal del AOSP (plataforma) y la política específica del dispositivo (proveedor). El flujo de compilación de la política de SELinux para Android 4.4 a Android 7.0 combinó todos los fragmentos de sepolicy y, luego, generó archivos monolíticos en el directorio raíz. Esto significaba que los proveedores de SoC y los fabricantes de ODM modificaban boot.img (para dispositivos que no son A/B) o system.img (para dispositivos A/B) cada vez que se modificaba la política.

En Android 8.0 y versiones posteriores, la política de la plataforma y del proveedor se compila por separado. Los SOC y los OEM pueden actualizar sus partes de la política, compilar sus imágenes (como vendor.img y boot.img) y, luego, actualizar esas imágenes independientemente de las actualizaciones de la plataforma.

Sin embargo, como los archivos de políticas de SELinux modularizados se almacenan en particiones /vendor, el proceso init debe activar las particiones del sistema y del proveedor antes para poder leer los archivos de SELinux de esas particiones y combinarlos con los archivos de SELinux principales en el directorio del sistema (antes de cargarlos en el kernel).

Archivos de origen

La lógica para compilar SELinux se encuentra en estos archivos:

  • external/selinux: Proyecto externo de SELinux que se usa para compilar utilidades de línea de comandos HOST para compilar políticas y etiquetas de SELinux.
    • external/selinux/libselinux: Android usa solo un subconjunto del proyecto externo libselinux junto con algunas personalizaciones específicas de Android. Para obtener más información, consulta external/selinux/README.android.
    • external/selinux/libsepol:
      • chkcon: Determina si un contexto de seguridad es válido para una política binaria determinada (ejecutable del host).
      • libsepol: Biblioteca de SELinux para manipular políticas de seguridad binarias (biblioteca estática o compartida del host, biblioteca estática del destino).
    • external/selinux/checkpolicy: Compilador de políticas de SELinux (ejecutables del host: checkpolicy, checkmodule y dispol). Depende de libsepol.
  • system/sepolicy: Configuraciones principales de la política de SELinux de Android, incluidos los contextos y los archivos de política. La lógica principal de compilación de sepolicy también se encuentra aquí (system/sepolicy/Android.mk).

Para obtener más detalles sobre los archivos en system/sepolicy, consulta Implementación de SELinux.

Android 7.x y versiones anteriores

En esta sección, se explica cómo se compila la política de SELinux en Android 7.x y versiones anteriores.

Proceso de compilación para Android 7.x y versiones anteriores

La política de SELinux se crea combinando la política principal del AOSP con las personalizaciones específicas del dispositivo. Luego, la política combinada se pasa al compilador de políticas y a varios verificadores. La personalización específica del dispositivo se realiza a través de la variable BOARD_SEPOLICY_DIRS definida en el archivo Boardconfig.mk específico del dispositivo. Esta variable de compilación global contiene una lista de directorios que especifican el orden en el que se deben buscar archivos de políticas adicionales.

Por ejemplo, un proveedor de SoC y un ODM podrían agregar un directorio cada uno, uno para la configuración específica del SoC y otro para la configuración específica del dispositivo, para generar las configuraciones finales de SELinux para un dispositivo determinado:

  • BOARD_SEPOLICY_DIRS += device/SOC/common/sepolicy
  • BOARD_SEPOLICY_DIRS += device/SoC/DEVICE/sepolicy

El contenido de los archivos file_contexts en system/sepolicy y BOARD_SEPOLICY_DIRS se concatena para generar el file_contexts.bin en el dispositivo:

En esta imagen, se muestra la lógica de compilación de SELinux para Android 7.x.

Figura 1: Lógica de compilación de SELinux.

El archivo sepolicy consta de varios archivos fuente:

  • El texto sin formato policy.conf se genera concatenando los archivos security_classes, initial_sids, *.te, genfs_contexts y port_contexts en ese orden.
  • Para cada archivo (como security_classes), su contenido es la concatenación de los archivos con el mismo nombre en system/sepolicy/ y BOARDS_SEPOLICY_DIRS.
  • El archivo policy.conf se envía al compilador de SELinux para que se verifique la sintaxis y se compile en formato binario como sepolicy en el dispositivo.
    En esta imagen, se muestran los archivos que generan el archivo de política de SELinux para Android 7.x.

    Figura 2: Es el archivo de política de SELinux.

Archivos de SELinux

Después de la compilación, los dispositivos Android que ejecutan la versión 7.x y versiones anteriores suelen contener los siguientes archivos relacionados con SELinux:

  • selinux_version
  • sepolicy: Es el resultado binario después de combinar los archivos de políticas (como security_classes, initial_sids y *.te).
  • file_contexts
  • property_contexts
  • seapp_contexts
  • service_contexts
  • system/etc/mac_permissions.xml

Para obtener más detalles, consulta Cómo implementar SELinux.

Inicialización de SELinux

Cuando se inicia el sistema, SELinux está en modo permisivo (y no en modo de aplicación forzosa). El proceso de init realiza las siguientes tareas:

  • Carga archivos sepolicy desde el disco RAM al kernel a través de /sys/fs/selinux/load.
  • Cambia SELinux al modo de aplicación forzosa.
  • Ejecuta re-exec() para aplicar la regla de dominio de SELinux a sí mismo.

Para acortar el tiempo de inicio, realiza el re-exec() en el proceso init lo antes posible.

Android 8.0 y versiones posteriores

En Android 8.0, la política de SELinux se divide en componentes de plataforma y de proveedor para permitir actualizaciones independientes de la política de plataforma o de proveedor y, al mismo tiempo, mantener la compatibilidad.

La sepolicy de la plataforma se divide aún más en partes privadas y públicas para exportar tipos y atributos específicos a los redactores de políticas del proveedor. Se garantiza que los tipos y atributos públicos de la plataforma se mantendrán como APIs estables para una versión determinada de la plataforma. La compatibilidad con tipos y atributos públicos de la plataforma anteriores se puede garantizar para varias versiones con archivos de asignación de la plataforma.

Proceso de compilación para Android 8.0

La política de SELinux en Android 8.0 se crea combinando fragmentos de /system y /vendor. La lógica para configurar esto de forma adecuada se encuentra en /platform/system/sepolicy/Android.mk.

La política existe en las siguientes ubicaciones:

Ubicación Contiene
system/sepolicy/public La API de sepolicy de la plataforma
system/sepolicy/private Detalles de la implementación de la plataforma (los proveedores pueden ignorarlos)
system/sepolicy/vendor Archivos de política y contexto que pueden usar los proveedores (los proveedores pueden ignorarlos si lo desean)
BOARD_SEPOLICY_DIRS sepolicy del proveedor
BOARD_ODM_SEPOLICY_DIRS (Android 9 y versiones posteriores) Odm sepolicy
SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 y versiones posteriores) API de sepolicy de system_ext
SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 y versiones posteriores) Detalles de implementación de system_ext (los proveedores pueden ignorarlos)
PRODUCT_PUBLIC_SEPOLICY_DIRS (Android 11 y versiones posteriores) API de sepolicy del producto
PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 y versiones posteriores) Detalles de la implementación del producto (los proveedores pueden ignorarlos)

El sistema de compilación toma esta política y produce componentes de política de sistema, system_ext, producto, proveedor y odm en la partición correspondiente. Estos son los pasos que debes seguir:

  1. Convierte las políticas al formato de lenguaje intermedio común (CIL) de SELinux, específicamente:
    1. Política de la plataforma pública (sistema + system_ext + producto)
    2. política combinada de privacidad y pública
    3. política de BOARD_SEPOLICY_DIRS pública y de proveedores
  2. Control de versiones de la política proporcionada por el público como parte de la política del proveedor. Se realiza con la política de CIL pública producida para informar a la política combinada pública + del proveedor + BOARD_SEPOLICY_DIRS qué partes deben convertirse en atributos que se vincularán a la política de la plataforma.
  3. Crea un archivo de asignación que vincule las partes de la plataforma y del proveedor. Inicialmente, esto solo vincula los tipos de la política pública con los atributos correspondientes en la política del proveedor. Más adelante, también proporcionará la base para el archivo que se mantendrá en versiones futuras de la plataforma, lo que permitirá la compatibilidad con la política del proveedor que segmenta los anuncios para esta versión de la plataforma.
  4. Combinación de archivos de políticas (describe las soluciones tanto en el dispositivo como las precompiladas)
    1. Combina la política de asignación, la política de la plataforma y la política del proveedor.
    2. Compila el archivo de política binaria de salida.

Política de seguridad pública de la plataforma

La política de seguridad pública de la plataforma incluye todo lo que se define en system/sepolicy/public. La plataforma puede suponer que los tipos y atributos definidos en la política pública son APIs estables para una versión de la plataforma determinada. Esto forma parte de la sepolicy que exporta la plataforma en la que los desarrolladores de políticas del proveedor (es decir, del dispositivo) pueden escribir políticas adicionales específicas del dispositivo.

Los tipos se versionan según la versión de la política con la que se escriben los archivos del proveedor, que se define con la variable de compilación PLATFORM_SEPOLICY_VERSION. Luego, la política pública versionada se incluye en la política del proveedor y (en su forma original) en la política de la plataforma. Por lo tanto, la política final incluye la política privada de la plataforma, la política pública de sepolicy de la plataforma actual, la política específica del dispositivo y la política pública versionada correspondiente a la versión de la plataforma para la que se escribió la política del dispositivo.

Política de SELinux privada de la plataforma

La política de SELinux privada de la plataforma incluye todo lo que se define en /system/sepolicy/private. Esta parte de la política establece los tipos, los permisos y los atributos exclusivos de la plataforma que se requieren para la funcionalidad de la plataforma. Estos no se exportan a los redactores de políticas de vendor/device. Los redactores de políticas que no son de la plataforma no deben escribir sus extensiones de políticas en función de los tipos, los atributos o las reglas definidos en la política de seguridad privada de la plataforma. Además, estas reglas se pueden modificar o desaparecer como parte de una actualización solo del framework.

Asignación privada de la plataforma

La asignación privada de la plataforma incluye declaraciones de políticas que asignan los atributos expuestos en la política pública de la plataforma de las versiones anteriores a los tipos concretos que se usan en la política pública de seguridad actual de la plataforma. Esto garantiza que la política del proveedor que se escribió en función de los atributos públicos de la plataforma de las versiones anteriores de la política de seguridad pública de la plataforma siga funcionando. El control de versiones se basa en la variable de compilación PLATFORM_SEPOLICY_VERSION establecida en el AOSP para una versión de plataforma determinada. Existe un archivo de asignación independiente para cada versión anterior de la plataforma desde la que se espera que esta plataforma acepte la política del proveedor. Para obtener más información, consulta Compatibilidad.

Android 11 y versiones posteriores

system_ext y sepolicy del producto

En Android 11, se agregan la política de system_ext y la política de producto. Al igual que la política de sepolicy de la plataforma, la política de system_ext y la política de producto se dividen en política pública y política privada.

La política pública se exporta al proveedor. Los tipos y atributos se convierten en una API estable, y la política del proveedor puede hacer referencia a los tipos y atributos de la política pública. Los tipos se versionan según PLATFORM_SEPOLICY_VERSION, y la política versionada se incluye en la política del proveedor. La política original se incluye en cada partición de system_ext y de producto.

La política privada contiene tipos, permisos y atributos solo para system_ext y solo para productos que se requieren para la funcionalidad de las particiones system_ext y de productos. La política privada es invisible para el proveedor, lo que implica que estas reglas son internas y se pueden modificar.

system_ext y asignación de productos

system_ext y product pueden exportar sus tipos públicos designados al proveedor. Sin embargo, cada socio es responsable de mantener la compatibilidad. Para garantizar la compatibilidad, los socios pueden proporcionar sus propios archivos de asignación que asignen los atributos versionados de versiones anteriores a los tipos concretos que se usan en la política de seguridad pública actual.

  • Para instalar un archivo de asignación para system_ext, coloca un archivo cil que contenga la información de asignación deseada en {SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil y, luego, agrega system_ext_{ver}.cil a PRODUCT_PACKAGES.
  • Para instalar un archivo de asignación para el producto, coloca un archivo cil que contenga la información de asignación deseada en {PRODUCT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil y, luego, agrega product_{ver}.cil a PRODUCT_PACKAGES.

Consulta un ejemplo que agrega un archivo de asignación de la partición de productos del dispositivo Redbull.

Política de SELinux precompilada

Antes de que init active SELinux, recopila todos los archivos CIL de las particiones (system, system_ext, product, vendor y odm) y los compila en una política binaria, que es el formato que se puede cargar en el kernel.init Como la compilación lleva tiempo (por lo general, de 1 a 2 segundos), los archivos CIL se precompilan durante la compilación y se colocan en /vendor/etc/selinux/precompiled_sepolicy o /odm/etc/selinux/precompiled_sepolicy, junto con los hashes sha256 de los archivos CIL de entrada. En el tiempo de ejecución, init verifica si se actualizó alguno de los archivos de políticas comparando los hashes. Si no hubo cambios, init carga la política precompilada. De lo contrario, init se compila sobre la marcha y se usa en lugar del compilado previamente.

Más específicamente, se usa la política precompilada si se cumplen todas las siguientes condiciones. Aquí, {partition} representa la partición en la que existe la política precompilada: vendor o odm.

  • /system/etc/selinux/plat_sepolicy_and_mapping.sha256 y /{partition}/etc/selinux/precompiled_sepolicy.plat_sepolicy_and_mapping.sha256 existen y son idénticos.
  • No existen /system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256 ni /{partition}/etc/selinux/precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256. O bien ambos existen y son idénticos.
  • No existen /product/etc/selinux/product_sepolicy_and_mapping.sha256 ni /{partition}/etc/selinux/precompiled_sepolicy.product_sepolicy_and_mapping.sha256. O bien ambos existen y son idénticos.

Si alguno de ellos difiere, init recurre a la ruta de compilación en el dispositivo. Consulta system/core/init/selinux.cpp para obtener más detalles.