Construyendo una política SELinux

Este artículo cubre cómo se construye la política SELinux. La política de SELinux se construye a partir de la combinación de la política central 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 hasta Android 7.0 fusionó todos los fragmentos de política y luego generó archivos monolíticos en el directorio raíz. Esto significaba que los proveedores de SoC y 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 plataforma y proveedor se crea por separado. Los SOC y OEM pueden actualizar sus partes de la política, crear 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 SELinux modularizados se almacenan en particiones /vendor , el proceso init debe montar las particiones del sistema y del proveedor antes para poder leer los archivos SELinux de esas particiones y fusionarlos con los archivos principales 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 SELinux externo, 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 : determina si un contexto de seguridad es válido para una política binaria determinada (ejecutable del host).
      • libsepol : biblioteca SELinux para manipular políticas de seguridad binarias (biblioteca estática/compartida de 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 principales de Android SELinux, incluidos contextos y archivos de políticas. La principal lógica 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 Implementación de SELinux .

Android 7.0 y anteriores

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

Construyendo la política SELinux

La política SELinux se crea combinando la política central 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 podrían agregar cada uno un directorio, uno para las configuraciones específicas de SoC y otro para las configuraciones específicas 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 construcción de SELinux

El archivo sepolicy consta de varios archivos fuente:

  • El policy.conf 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 .
  • 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ítica SELinux para Android 7.x.
    Figura 2 . Archivo de política 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 obligatorio). El proceso de inicio realiza las siguientes tareas:

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

Para acortar el tiempo de inicio, realice re-exec() en el proceso 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 la política de plataforma/proveedor manteniendo la compatibilidad.

La política de plataforma se divide a su vez en partes de plataforma privada y plataforma pública para exportar tipos y atributos específicos a los redactores 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. La compatibilidad con los tipos/atributos públicos de la plataforma anterior se puede garantizar para varias versiones utilizando archivos de mapeo de plataforma.

Plataforma de política pública

La plataforma public sepolicy 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 se exporta por 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 tienen versiones de acuerdo con la versión de la política en 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 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 en la que se escribió la política del dispositivo.

Plataforma de política privada.

La política privada de la plataforma incluye todo lo definido en /system/sepolicy/private . Esta parte de la política establece tipos, permisos y atributos exclusivos de la plataforma necesarios 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 pertenecen a la plataforma no deben escribir sus extensiones de políticas basándose en tipos/atributos/reglas definidas en la política privada de la plataforma. Además, estas reglas pueden modificarse o desaparecer como parte de una actualización exclusiva del marco.

Mapeo privado de plataforma

El mapeo privado de la plataforma incluye declaraciones de políticas que mapean los atributos expuestos en la política pública de la plataforma de las versiones anteriores de la plataforma con los tipos concretos utilizados en la política pública de la plataforma actual. Esto garantiza que la política del proveedor escrita en función de los atributos públicos de la plataforma de las versiones anteriores de la política 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 mapeo separado para cada versión de plataforma anterior a partir de la cual 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 convierten en 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 exclusivos de system_ext y de producto necesarios para la funcionalidad de system_ext y de las particiones de producto. La política privada es invisible para el proveedor, lo que implica que estas reglas son internas y pueden modificarse.

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. Para mayor compatibilidad, los socios pueden proporcionar sus propios archivos de mapeo que asignan los atributos versionados de versiones anteriores a tipos concretos utilizados en la política pública actual.

  • Para instalar un archivo de mapeo para system_ext, coloque un archivo cil que contenga la información de mapeo 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 mapeo para el producto, coloque un archivo cil que contenga la información de mapeo 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 SELinux

    La política SELinux en Android 8.0 se crea combinando piezas de /system y /vendor . La lógica para configurar esto adecuadamente está 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 implementación de la plataforma (los proveedores pueden ignorarlos)
    system/sepolicy/vendor Archivos de políticas y contexto que los proveedores pueden usar (los proveedores pueden ignorarlos si lo desean)
    BOARD_SEPOLICY_DIRS Política del proveedor
    BOARD_ODM_SEPOLICY_DIRS (Android 9 y superior) Política Odm
    SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 y superior) API de política de System_ext
    SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 y superior) Detalles de implementación de System_ext (los proveedores pueden ignorarlos)
    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 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. Los pasos incluyen:

    1. Conversión de políticas al formato de lenguaje intermedio común (CIL) de SELinux, específicamente:
      1. política de plataforma pública (sistema + system_ext + producto)
      2. política pública + privada combinada
      3. público + proveedor y política BOARD_SEPOLICY_DIRS
    2. Versionar la política proporcionada por el público como parte de la política del proveedor. Se realiza utilizando la política 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 mapeo que vincule la plataforma y las partes del proveedor. Inicialmente, esto simplemente 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 mantenido 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. Combinar archivos de políticas (describir soluciones precompiladas y en el dispositivo).
      1. Combine mapeo, plataforma y política de proveedores.
      2. Compile el archivo de política binaria de salida.

    Política 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 (normalmente entre 1 y 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 hash sha256. de los archivos CIL de entrada. En tiempo de ejecución, init comprueba si alguno de los archivos de políticas se ha actualizado comparando los hashes. 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, se utiliza una política precompilada 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 vuelve a la ruta de compilación del dispositivo. Consulte system/core/init/selinux.cpp para obtener más detalles.