Implementa SELinux

SELinux está configurado para denegar de forma predeterminada, lo que significa que la política debe permitir de forma explícita cada acceso para el que tiene un hook en el kernel. Esto significa que un archivo de directivas consta de una gran cantidad de información sobre reglas, tipos, clases, permisos y mucho más. Una consideración completa de SELinux está fuera del alcance de este documento, pero comprender cómo escribir reglas de políticas ahora es esencial cuando se inician nuevos dispositivos Android. Ya hay una gran cantidad de información disponible sobre SELinux. Consulta Documentación de asistencia para ver los recursos sugeridos.

Archivos de claves

Para habilitar SELinux, integra el kernel de Android más reciente y, luego, incorpora los archivos que se encuentran en el directorio system/sepolicy. Cuando se compilan, esos archivos comprenden la seguridad del kernel de SELinux y abarcan el sistema operativo Android ascendente.

En general, no debes modificar los archivos system/sepolicy directamente. En su lugar, agrega o edita tus propios archivos de políticas específicos para dispositivos en la /device/manufacturer/device-name/sepolicy . En Android 8.0 y versiones posteriores, los cambios que realices en estos archivos deberían solo afectan a la política del directorio de proveedores. Para obtener más detalles sobre la separación de sepolicy pública en Android 8.0 y versiones posteriores, consulta Cómo personalizar SEPolicy en Android 8.0 o versiones posteriores. Independientemente de la versión de Android, seguirás modificando estos archivos:

Archivos de políticas

Los archivos que terminan en *.te son archivos de origen de la política de SELinux, que definen los dominios y sus etiquetas. Es posible que debas crear nuevos archivos de políticas en /device/manufacturer/device-name/sepolicy, pero intenta actualizar los archivos existentes siempre que sea posible.

Archivos de contexto

En los archivos de contexto, especificas etiquetas para tus objetos.

  • file_contexts asigna etiquetas a los archivos y lo usan varios del espacio del usuario. A medida que crees políticas nuevas, crea o actualiza este archivo para asignar etiquetas nuevas a los archivos. Para aplicar un nuevo file_contexts, vuelve a compilar la imagen del sistema de archivos o ejecuta restorecon en el archivo que se volverá a etiquetar. Durante las actualizaciones, se aplicarán los cambios a file_contexts automáticamente al sistema y a las particiones de userdata como parte del actualización. Los cambios también se pueden aplicar automáticamente cuando se actualizan a otras particiones. Para ello, agrega llamadas restorecon_recursive a tu archivo init.board.rc después de que la partición se haya activado en modo de lectura y escritura.
  • genfs_contexts asigna etiquetas a sistemas de archivos, como proc o vfat, que no admiten atributos extendidos. Esta configuración se carga como parte de la política del kernel, pero es posible que los cambios no se apliquen a los inodos en el kernel, lo que requiere un reinicio o la desactivación y activación del sistema de archivos para aplicar el cambio por completo. También se pueden asignar etiquetas específicas a activaciones específicas, como vfat, con la opción context=mount.
  • property_contexts asigna etiquetas a las propiedades del sistema Android para controlar qué procesos pueden establecerlas. El proceso init lee esta configuración durante el inicio.
  • service_contexts asigna etiquetas a los servicios de Binder de Android para controlar qué procesos pueden agregar (registrar) y encontrar (buscar) un Binder referencia del servicio. El administrador lee esta configuración servicemanager durante el inicio.
  • seapp_contexts asigna etiquetas a los procesos de la app y /data/data directorios. El administrador lee esta configuración Proceso de zygote en cada inicio de la app y antes del installd durante el inicio.
  • mac_permissions.xml asigna una etiqueta seinfo a las apps según su firma y, de manera opcional, su nombre de paquete. Luego, la etiqueta seinfo se puede usar como clave en el archivo seapp_contexts para asignar una etiqueta específica a todas las apps con esa etiqueta seinfo. system_server lee esta configuración durante el inicio.
  • keystore2_key_contexts asigna etiquetas a los espacios de nombres de Keystore 2.0. El daemon keystore2 aplica estos espacios de nombres. El almacén de claves siempre proporcionó espacios de nombres basados en UID/AID. Keystore 2.0 también aplica espacios de nombres definidos por la política de seguridad. Una descripción detallada de su formato y convenciones aquí.

Archivo de configuración de make BoardConfig.mk

Después de editar o agregar archivos de políticas y contexto, actualiza tu /device/manufacturer/device-name/BoardConfig.mk Make para hacer referencia al subdirectorio sepolicy y a cada archivo de política nuevo. Para obtener más información sobre las variables BOARD_SEPOLICY, consulta el archivo system/sepolicy/README.

BOARD_SEPOLICY_DIRS += \
        <root>/device/manufacturer/device-name/sepolicy

BOARD_SEPOLICY_UNION += \
        genfs_contexts \
        file_contexts \
        sepolicy.te

Después de volver a compilar, el dispositivo quedará habilitado con SELinux. Ahora puedes personalizar tus políticas de SELinux para admitir tus propias incorporaciones al sistema operativo Android, como se describe en Personalización, o verificar tu configuración existente, como se explica en Validación.

Cuando los nuevos archivos de política y las actualizaciones de BoardConfig.mk estén en su lugar, el nuevo la configuración de la política se integra automáticamente en el archivo de política del kernel final. Para obtener más información sobre cómo se crea la política en el dispositivo, consulta Compilación de la política.

Implementación

Para comenzar a usar SELinux, sigue estos pasos:

  1. Habilita SELinux en el kernel: CONFIG_SECURITY_SELINUX=y
  2. Cambia el parámetro kernel_cmdline o bootconfig para que sea lo siguiente:
    BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    o
    BOARD_BOOTCONFIG := androidboot.selinux=permissive
    Esto es solo para el desarrollo inicial de la política del dispositivo. Después de tener una política de inicio inicial, quita este parámetro para que el dispositivo aplique CTS o falle.
  3. Inicia el sistema en modo permisivo y observa qué rechazos se producen durante el inicio:
    En Ubuntu 14.04 o versiones posteriores:
    adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
    
    En Ubuntu 12.04:
    adb pull /sys/fs/selinux/policy
    adb logcat -b all | audit2allow -p policy
    
  4. Evalúa el resultado en busca de advertencias similares a init: Warning! Service name needs a SELinux domain defined; please fix!. Consulta Validación de las instrucciones y herramientas de la nube.
  5. Identifica dispositivos y otros archivos nuevos que deben etiquetar.
  6. Usa etiquetas existentes o nuevas para tus objetos. Consulta *_contexts de archivos para ver cómo se etiquetaron anteriormente y usar el conocimiento de los significados de las etiquetas para asignar una nueva. Idealmente, esta es una etiqueta existente que se ajusta a la política, pero, a veces, se necesita una etiqueta nueva y reglas para acceder a ella. Agrega tus etiquetas a los archivos de contexto adecuados.
  7. Identifica los dominios o procesos que deberían tener sus propios dominios de seguridad. Es probable que debas escribir una política completamente nueva para cada una. Todas servicios generados a partir de init, por ejemplo, deben tener su por sí solas. Los siguientes comandos ayudan a revelar aquellos que permanecen en ejecución (pero TODAS servicios necesitan ese tratamiento):
    adb shell su -c ps -Z | grep init
    
    adb shell su -c dmesg | grep 'avc: '
    
  8. Revisa init.device.rc para identificar los dominios que que no tienen un tipo de dominio. Otórgale un dominio al principio del proceso de desarrollo para evitar agregar reglas a init o confundir los accesos de init con los que se encuentran en su propia política.
  9. Configura BOARD_CONFIG.mk para usar BOARD_SEPOLICY_* variables. Consulta el archivo README en system/sepolicy para obtener detalles sobre cómo configurarlo.
  10. Examina los archivos init.device.rc y fstab.device y asegúrate de que cada uso de mount corresponda a un sistema de archivos etiquetado correctamente o de que se especifique una opción context= mount.
  11. Revisa cada rechazo y crea una política SELinux para controlar cada uno de manera correcta. Consulta los ejemplos en Personalización.

Debes comenzar con las políticas del AOSP y, luego, basarte en ellas para tus propias personalizaciones. Para obtener más información sobre la estrategia de políticas un análisis más detallado de algunos de estos pasos, Escribe la política de SELinux.

Casos de uso

Estos son ejemplos específicos de exploits que debes tener en cuenta cuando diseñes el tuyo y las políticas de SELinux asociadas:

Vínculos simbólicos: Debido a que los vínculos simbólicos aparecen como archivos, a menudo se leen como archivos, lo que puede generar exploits. Por ejemplo, algunos componentes con privilegios, como init, cambian los permisos de ciertos archivos, a veces para que sean demasiado abiertos.

Luego, los atacantes pueden reemplazar esos archivos por symlinks al código que controlan, lo que les permite reemplazar archivos arbitrarios. Pero si sabes La app nunca desvía un symlink, puedes prohibirle que lo haga. con SELinux.

Archivos del sistema: Ten en cuenta la clase de archivos del sistema que solo las puede modificar el servidor del sistema. Sin embargo, como netd, init y vold se ejecutan como root, pueden acceder a esos archivos del sistema. Por lo tanto, si netd se vio comprometido, podría comprometer esos archivos y potencialmente el propio servidor del sistema.

Con SELinux, puedes identificar esos archivos como archivos de datos del servidor del sistema. Por lo tanto, el único dominio que tiene acceso de lectura/escritura a ellos es el servidor del sistema. Incluso si netd se veía comprometido, no pudo cambiar de dominio al dominio del servidor del sistema y acceder a los archivos del sistema aunque se ejecute como raíz.

Datos de apps: Otro ejemplo es la clase de funciones que deben ejecutarse como root, pero que no deben acceder a los datos de la app. Esto es increíblemente útiles, ya que se pueden realizar aserciones de mayor alcance, como ciertos dominios no relacionados, a que los datos de las apps tengan prohibido acceder a Internet.

setattr: Para comandos como chmod y chown, puedes identificar el conjunto de archivos en los que el dominio asociado puede realizar setattr. Cualquier cosa fuera de eso podría estar prohibida para estos cambios, incluso por root. Por lo tanto, una app podría ejecutar chmod y chown en los elementos etiquetados como app_data_files, pero no en shell_data_files ni system_data_files.