Construyendo una política SELinux

Este artículo cubre cómo se construye la política de SELinux. La política de SELinux se crea 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 políticas de SELinux para Android 4.4 a Android 7.0 combinó todos los fragmentos de políticas y luego generó archivos monolíticos en el directorio raíz. Esto significó que los proveedores de SoC y los fabricantes de ODM modificaron 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 plataforma y proveedor se crea por separado. Los SOC y los OEM pueden actualizar sus partes de la política, crear sus imágenes (como, por ejemplo, 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 de init debe montar las particiones del sistema y del proveedor antes para que pueda leer los archivos SELinux de esas particiones y fusionarlos con los archivos centrales de SELinux en el directorio del sistema (antes de cargarlos en el núcleo).

Archivos fuente

La lógica para construir SELinux está en estos archivos:

  • external/selinux : proyecto externo de SELinux, utilizado para crear 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 libselinux externo junto con algunas personalizaciones específicas de Android. Para obtener más información, consulte external/selinux/README.android .
    • external/selinux/libsepol :
      • chkcon : determine si un contexto de seguridad es válido para una política binaria determinada (ejecutable de host).
      • libsepol : biblioteca SELinux para manipular políticas de seguridad binaria (biblioteca estática/compartida del host, biblioteca estática de destino).
    • external/selinux/checkpolicy : compilador de políticas de SELinux (ejecutables del host: checkpolicy , checkmodule y dispol ). Depende de libsepol .
  • system/sepolicy : Configuraciones de políticas básicas de Android SELinux, incluidos contextos y archivos de políticas. La principal lógica de compilación de sepolicy también está aquí ( system/sepolicy/Android.mk ).

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

Android 7.0 y anteriores

Esta sección cubre cómo se construye la política de SELinux en Android 7.x y versiones anteriores.

Construyendo la política de SELinux

La política de SELinux se crea al combinar 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 buscar archivos de políticas adicionales.

Por ejemplo, un proveedor de SoC y un ODM pueden agregar cada uno un directorio, uno para la configuración específica de 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 concatenan para generar file_contexts.bin en el dispositivo:

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

  • El policy.conf de texto sin formato 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 SELinux para verificar la sintaxis y se compila en formato binario como sepolicy en el dispositivo.
    Esta imagen muestra los archivos que generan el archivo de políticas de SELinux para Android 7.x.
    Figura 2 . Archivo de políticas de SELinux

Archivos 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, consulte Implementación de SELinux .

Inicialización de SELinux

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

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

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

Android 8.0 y superior

En Android 8.0, la política de SELinux se divide en componentes de plataforma y proveedor para permitir actualizaciones independientes de políticas de plataforma/proveedor mientras se mantiene la compatibilidad.

La política de plataforma se divide aún más en partes de plataforma privada y de plataforma pública para exportar tipos y atributos específicos a los escritores de políticas de proveedores. Se garantiza que los tipos/atributos públicos de la plataforma se mantendrán como API estables para una versión de plataforma determinada. Se puede garantizar la compatibilidad con los tipos/atributos públicos de la plataforma anterior para varias versiones utilizando archivos de asignación de plataforma.

Política pública de la plataforma

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

Los tipos se controlan según la versión de la política contra la que se escriben los archivos del proveedor, definida por la variable de compilación PLATFORM_SEPOLICY_VERSION . La política pública versionada luego 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 versionada correspondiente a la versión de la plataforma contra la cual se escribió la política del dispositivo.

Política de privacidad de la plataforma

La política privada de la plataforma incluye todo lo definido en /system/sepolicy/private . Esta parte de la política forma los tipos, permisos y atributos exclusivos de la plataforma necesarios para la funcionalidad de la plataforma. Estos no se exportan a los escritores de políticas del vendor/device . Los redactores de políticas que no sean de plataforma no deben escribir sus extensiones de política en función de los tipos/atributos/reglas definidas en la política privada de la plataforma. Además, estas reglas pueden modificarse o pueden desaparecer como parte de una actualización solo del marco.

Mapeo privado de plataforma

El mapeo privado 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 utilizados en la política 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 política de seguridad pública de la plataforma continúe 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 de la que se espera que esta plataforma acepte la política del proveedor. Para obtener más detalles, consulte Compatibilidad .

Android 11 y superior

system_ext y política de producto

En Android 11, se agregan la política system_ext y la política de producto. Al igual que la política de plataforma, la política 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 vuelven API estables, y la política del proveedor puede hacer referencia a tipos y atributos en 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 de system_ext-only y product-only necesarios para la funcionalidad de system_ext y las particiones 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 mapeo de 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. Por motivos de compatibilidad, los socios pueden proporcionar sus propios archivos de asignación que asignan los atributos versionados de versiones anteriores a tipos concretos utilizados en la política pública actual.

  • Para instalar un archivo de asignación para system_ext, coloque un archivo cil que contenga la información de asignación deseada en {SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil y luego agregue system_ext_{ver}.cil a PRODUCT_PACKAGES .
  • Para instalar un archivo de asignación para el producto, coloque un archivo cil que contenga la información de asignación deseada en {PRODUCT_PRIVATE_SEPOLICY_DIRS}/compat/{ver}/{ver}.cil y luego agregue product_{ver}.cil a PRODUCT_PACKAGES .
  • Consulte un ejemplo que agrega un archivo de mapeo de la partición del producto del dispositivo redbull.

    Construyendo la política de SELinux

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

    La póliza 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 ignorar)
    system/sepolicy/vendor Archivos de política y contexto que los proveedores pueden usar (los proveedores pueden ignorar si lo desean)
    BOARD_SEPOLICY_DIRS Política de proveedores
    BOARD_ODM_SEPOLICY_DIRS (Android 9 y superior) Política de privacidad
    SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 y superior) API de política de seguridad de System_ext
    SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 y superior) Detalles de implementación de System_ext (los proveedores pueden ignorar)
    PRODUCT_PUBLIC_SEPOLICY_DIRS (Android 11 y superior) API de política de seguridad del producto
    PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 y superior) Detalles de implementación del producto (los proveedores pueden ignorar)

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

    1. Conversión de políticas al formato Common Intermediate Language (CIL) de SELinux, específicamente:
      1. política de plataforma pública (sistema + system_ext + producto)
      2. política privada + pública combinada
      3. público + proveedor y política BOARD_SEPOLICY_DIRS
    2. Versión de la política proporcionada por público como parte de la política del proveedor. Se realiza mediante el uso de la política CIL pública producida para informar a la política combinada pública + proveedor + BOARD_SEPOLICY_DIRS sobre qué partes deben convertirse en atributos que se vincularán a la política de la plataforma.
    3. Creación de un archivo de mapeo que vincula la plataforma y las partes 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 tarde, también proporcionará la base para el archivo que se mantendrá en futuras versiones de la plataforma, lo que permitirá la compatibilidad con la política del proveedor dirigida a esta versión de la plataforma.
    4. Combinación de archivos de políticas (describa tanto las soluciones en el dispositivo como las precompiladas).
      1. Combine mapeo, plataforma y política de proveedores.
      2. Compile el archivo de política binaria de salida.

    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 (generalmente de 1 a 2 segundos), los archivos CIL se compilan previamente 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 tiempo de ejecución, init comprueba si alguno de los archivos de política se ha actualizado comparando los valores hash. Si nada ha cambiado, init carga la política precompilada. Si no, init compila sobre la marcha y lo usa en lugar del precompilado.

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

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

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