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 de AOSP (plataforma) y la política específica del dispositivo (fabricante). El flujo de compilación de políticas de SELinux para Android 4.4 a Android 7.0 fusionó 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 OEMs pueden actualizar sus partes de la política, compilar sus imágenes (como vendor.img y boot.img) y, luego, actualizarlas 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 desde esas particiones y combinarlos con los archivos principales de SELinux 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: Es un proyecto externo de SELinux que se usa para compilar utilidades de línea de comandos de HOST para compilar etiquetas y políticas de SELinux.
    • external/selinux/libselinux: Android solo usa un subconjunto del proyecto libselinux externo 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 está aquí (system/sepolicy/Android.mk).

Para obtener más detalles sobre los archivos en system/sepolicy, consulta Implementa 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 de AOSP con 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 pueden agregar un directorio, 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 de 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 policy.conf se envía al compilador de SELinux para la verificación de sintaxis y se compila 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: Archivo de política de SELinux.

Archivos de SELinux

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

  • selinux_version
  • sepolicy: Salida binaria después de combinar 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 init realiza las siguientes tareas:

  • Carga archivos sepolicy del ramdisk en el kernel a través de /sys/fs/selinux/load.
  • Cambia SELinux al modo de aplicación forzosa.
  • Ejecuta re-exec() para aplicarle la regla de dominio de SELinux.

Para acortar el tiempo de inicio, realiza la 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 la plataforma y del proveedor para permitir actualizaciones independientes de la política de la plataforma o del proveedor y, al mismo tiempo, mantener la compatibilidad.

La política de seguridad de la plataforma se divide en partes públicas y privadas para exportar tipos y atributos específicos a los generadores de políticas de proveedores. Se garantiza que los tipos o atributos públicos de la plataforma se mantengan como APIs estables para una versión determinada de la plataforma. Se puede garantizar la compatibilidad con tipos o atributos públicos de la plataforma anteriores para varias versiones con archivos de asignación de plataformas.

Proceso de compilación para Android 8.0

La política de SELinux en Android 8.0 se crea combinando partes 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 Contenido
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 los proveedores pueden usar (los proveedores pueden ignorarlos si lo desean)
BOARD_SEPOLICY_DIRS Política de seguridad del proveedor
BOARD_ODM_SEPOLICY_DIRS (Android 9 y versiones posteriores) Sepolicy de Odm
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 la 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íticas de sistema, system_ext, producto, proveedor y odm en la partición correspondiente. Entre los pasos, se incluyen los siguientes:

  1. Conversión de políticas al formato de lenguaje intermedio común (CIL) de SELinux, en particular:
    1. política de plataforma pública (system + system_ext + product)
    2. política pública y privada combinada
    3. política pública y de proveedores, y BOARD_SEPOLICY_DIRS
  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 pública + proveedor + BOARD_SEPOLICY_DIRS combinada sobre qué partes deben convertirse en atributos que se vincularán a la política de la plataforma.
  3. Crear un archivo de asignación que vincule las partes de la plataforma y del proveedor En un principio, 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 mantiene en versiones futuras de la plataforma, lo que habilitará la compatibilidad con la política del proveedor segmentada para esta versión de la plataforma.
  4. Combinación de archivos de políticas (describe las soluciones integradas en el dispositivo y las precompiladas)
    1. Combina la asignación de mapas, 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 determinada de la plataforma. Esta forma la parte de la sepolicy que exporta la plataforma en la que los desarrolladores de políticas de proveedores (es decir, de dispositivos) pueden escribir políticas adicionales específicas del dispositivo.

Los tipos se controlan según la versión de la política con la que se escriben los archivos del proveedor, que define la variable de compilación PLATFORM_SEPOLICY_VERSION. Luego, la política pública con versión se incluye con 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 de plataforma privada, la política de seguridad pública de la plataforma actual, la política específica del dispositivo y la política pública con versión correspondiente a la versión de la plataforma para la que se escribió la política del dispositivo.

Política de seguridad privada de la plataforma

La política de seguridad privada de la plataforma incluye todo lo definido en /system/sepolicy/private. Esta parte de la política forma tipos, permisos y atributos solo de la plataforma necesarios para su funcionalidad. No se exportan a los generadores de políticas de vendor/device. Los redactores de políticas que no sean de la plataforma no deben escribir sus extensiones de políticas según los tipos, atributos o reglas definidos en la política de SE privada de la plataforma. Además, estas reglas se pueden modificar o pueden desaparecer como parte de una actualización solo del framework.

Creación de mapas privados 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 de la plataforma a los tipos concretos que se usan en la política de seguridad pública 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 de la plataforma siga funcionando. El control de versiones se basa en la variable de compilación PLATFORM_SEPOLICY_VERSION establecida en 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 agregaron la política system_ext y la política de productos. Al igual que la política de sepolicy de la plataforma, la política de system_ext y la política de productos 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 le asignan versiones según PLATFORM_SEPOLICY_VERSION, y la política con versión se incluye en la política del proveedor. La política original se incluye en cada una de las particiones system_ext y del producto.

La política privada contiene tipos, permisos y atributos solo para system_ext y solo para productos necesarios para la funcionalidad de las particiones system_ext y de productos. El proveedor no puede ver la política privada, lo que implica que estas reglas son internas y se pueden modificar.

Asignación de system_ext y productos

system_ext y product pueden exportar sus tipos públicos designados al proveedor. Sin embargo, la responsabilidad de mantener la compatibilidad es de cada socio. Para garantizar la compatibilidad, los socios pueden proporcionar sus propios archivos de asignación que asignan los atributos con versión de versiones anteriores a 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 de productos, 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, init reúne todos los archivos CIL de las particiones (system, system_ext, product, vendor y odm) y los compila en una política binaria, el formato que se puede cargar en el kernel. Como la compilación lleva tiempo (por lo general, de 1 a 2 segundos), los archivos CIL se precompilan en el tiempo de compilación y se colocan en /vendor/etc/selinux/precompiled_sepolicy o /odm/etc/selinux/precompiled_sepolicy, junto con los valores hash sha256 de los archivos CIL de entrada. Durante el tiempo de ejecución, init compara los valores hash para verificar si se actualizó alguno de los archivos de políticas. Si no cambió nada, init carga la política precompilada. De lo contrario, init se compila sobre la marcha y se usa en lugar del precompilado.

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.
  • /system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256 y /{partition}/etc/selinux/precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256 no existen. O bien ambos existen y son idénticos.
  • /product/etc/selinux/product_sepolicy_and_mapping.sha256 y /{partition}/etc/selinux/precompiled_sepolicy.product_sepolicy_and_mapping.sha256 no existen. O bien ambos existen y son idénticos.

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