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 (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ítica de SELinux modularizados se almacenan en particiones /vendor, el proceso init debe activar las particiones system y del proveedor antes para que pueda leer los archivos de SELinux de esas particiones y combinarlos con los archivos principales de SELinux en el directorio system (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 HOST para compilar la política y las 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: Es una biblioteca de SELinux para manipular políticas de seguridad binarias (biblioteca estática o compartida del host, biblioteca estática de destino).
    • external/selinux/checkpolicy: Es un compilador de políticas de SELinux (ejecutables del host: checkpolicy, checkmodule, y dispol). Depende de libsepol.
  • system/sepolicy: Son las configuraciones principales de la política de SELinux de Android, incluidos los contextos y los archivos de políticas. La lógica principal de compilación de sepolicy también se encuentra aquí (system/sepolicy/Android.mk).

Para obtener más información sobre los archivos en system/sepolicy, consulta Archivos clave.

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 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:

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 de origen:

  • El texto sin formato policy.conf se genera concatenando security_classes, initial_sids, archivos *.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.

    Archivos que generan el archivo de política de SELinux para Android 7.x
    Figura 2. Archivo de políticas 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: Es el resultado binario 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 información, 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). El proceso init realiza las siguientes tareas:

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

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

La sepolicy de la plataforma se divide aún más en partes públicas y privadas de la plataforma para exportar tipos y atributos específicos a los escritores de políticas del proveedor. Se garantiza que los tipos o atributos públicos de la plataforma se mantendrán como APIs estables para una versión determinada de la plataforma. La compatibilidad con los tipos o 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 partes de /system y /vendor. La lógica para configurar esto de forma adecuada se encuentra en /platform/system/sepolicy/Android.bp.

La política existe en las siguientes ubicaciones:

Ubicación Contiene
system/sepolicy/public API de sepolicy de la plataforma
system/sepolicy/private Detalles de implementación de la plataforma (los proveedores pueden ignorarlos)
system/sepolicy/vendor Archivos de políticas y de contexto que los proveedores pueden usar (los proveedores pueden ignorarlos)
BOARD_SEPOLICY_DIRS Sepolicy del proveedor
BOARD_ODM_SEPOLICY_DIRS (Android 9 y versiones posteriores) Sepolicy del 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 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 implementación del producto (los proveedores pueden ignorarlos)

El sistema de compilación toma esta política y produce system, system_ext, product, vendor y odm componentes de políticas en la partición correspondiente. Los pasos incluyen lo siguiente:

  1. Convierte las políticas al formato de lenguaje intermedio común (CIL) de SELinux, específicamente:
    • Política pública de la plataforma (system, system_ext, product)
    • Política pública y privada combinada
    • Política pública, del proveedor y BOARD_SEPOLICY_DIRS
  2. Controla la versión de la política proporcionada por el público como parte de la política del proveedor. Usa la política pública de CIL producida para informar a la política pública y del proveedor combinadas, y a la política BOARD_SEPOLICY_DIRS sobre qué partes se deben convertir en atributos vinculados 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 proporciona la base para el archivo que se mantiene en versiones futuras de la plataforma, lo que permite la compatibilidad con la política del proveedor que se orienta a esta versión de la plataforma.
  4. Combina archivos de políticas (describe las soluciones precompiladas e integradas en el dispositivo).
    1. Combina la política de asignación, de la plataforma y del proveedor.
    2. Compila el archivo de políticas binario de salida.

Sepolicy pública de la plataforma

La sepolicy 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. 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, definida por la variable de compilación PLATFORM_SEPOLICY_VERSION. Luego, la política pública versionada 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 privada de la plataforma, la sepolicy pública 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 con la que se escribió la política del dispositivo.

Sepolicy privada de la plataforma

La sepolicy privada de la plataforma incluye todo lo que se define en /system/sepolicy/private. Esta parte de la política forma tipos, permisos y atributos exclusivos de la plataforma que son necesarios para la funcionalidad de la plataforma. Estos no se exportan a los escritores de políticas del proveedor y del dispositivo. Los escritores de políticas que no son de la plataforma no deben escribir sus extensiones de políticas en función de los tipos, atributos y reglas definidos en la sepolicy 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 instrucciones 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 sepolicy pública de la plataforma actual. 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 sepolicy pública 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 determinada de la plataforma. 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 de políticas.

Android 11 y versiones posteriores

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

Sepolicy de system_ext y del producto

En Android 11, se agregan la política system_ext y la política product. Al igual que la sepolicy de la plataforma, la política system_ext y la política product 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 una de las particiones system_ext y product.

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

Asignación de system_ext y del producto

Se permite que system_ext y product exporten sus tipos públicos designados al proveedor. Sin embargo, cada socio tiene la responsabilidad de mantener la compatibilidad. Para 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 sepolicy 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 product, 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 product de un dispositivo Redbull.

Política de SELinux precompilada

Antes de que init active SELinux, init recopila 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 momento de 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 se modificó nada, init carga la política precompilada. De lo contrario, init compila sobre la marcha y la usa en lugar de la precompilada.

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.

  • Existen /system/etc/selinux/plat_sepolicy_and_mapping.sha256 y /{partition}/etc/selinux/precompiled_sepolicy.plat_sepolicy_and_mapping.sha256 , 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 vuelve a la ruta de compilación integrada en el dispositivo. Consulta system/core/init/selinux.cpp para obtener más detalles.