Google is committed to advancing racial equity for Black communities. See how.
Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Redacción de la política de SELinux

El Proyecto de código abierto de Android (AOSP) proporciona una política de base sólida para las aplicaciones y servicios que son comunes en todos los dispositivos Android. Los colaboradores de AOSP perfeccionan periódicamente esta política. Se espera que la política principal represente alrededor del 90-95% de la política final en el dispositivo y las personalizaciones específicas del dispositivo constituyan el 5-10% restante. Este artículo se centra en estas personalizaciones específicas del dispositivo, cómo escribir políticas específicas del dispositivo y algunas de las trampas que se deben evitar en el camino.

Mostrar dispositivo

Mientras escribe la política específica del dispositivo, siga estos pasos.

Ejecutar en modo permisivo

Cuando un dispositivo está en modo permisivo , las denegaciones se registran pero no se aplican. El modo permisivo es importante por dos razones:

  • El modo permisivo garantiza que la activación de la política no retrase otras tareas de activación temprana del dispositivo.
  • Una negación forzada puede enmascarar otras negaciones. Por ejemplo, el acceso a archivos normalmente implica una búsqueda de directorio, un archivo abierto y luego un archivo leído. En el modo de ejecución, solo se produciría la denegación de búsqueda de directorio. El modo permisivo garantiza que se vean todas las denegaciones.

La forma más sencilla de poner un dispositivo en modo permisivo es utilizando la línea de comandos del kernel . Esto se puede agregar al archivo BoardConfig.mk del dispositivo: platform/device/<vendor>/<target>/BoardConfig.mk . Después de modificar la línea de comando, realice make clean , luego make bootimage y make bootimage la nueva imagen de arranque.

Después de eso, confirme el modo permisivo con:

adb shell getenforce

Dos semanas es una cantidad de tiempo razonable para estar en modo permisivo global. Después de abordar la mayoría de las denegaciones, vuelva al modo de aplicación y resuelva los errores a medida que aparezcan. Los dominios que todavía producen denegaciones o los servicios que aún se encuentran en desarrollo pueden ponerse temporalmente en modo permisivo, pero vuelva a ponerlos en modo de aplicación lo antes posible.

Hacer cumplir temprano

En el modo de ejecución, las denegaciones se registran y se hacen cumplir. Es una buena práctica poner su dispositivo en modo de aplicación lo antes posible. Esperar para crear y hacer cumplir una política específica del dispositivo a menudo resulta en un producto con errores y una mala experiencia de usuario. Empiece con la suficiente antelación para participar en la prueba interna y garantizar una cobertura de prueba completa de la funcionalidad en el uso del mundo real. Comenzar temprano garantiza que las preocupaciones de seguridad informan las decisiones de diseño. Por el contrario, otorgar permisos basados ​​únicamente en denegaciones observadas es un enfoque inseguro. Utilice este tiempo para realizar una auditoría de seguridad del dispositivo y archivar errores contra comportamientos que no deberían permitirse.

Eliminar o eliminar la política existente

Hay una serie de buenas razones para crear una política específica de dispositivo desde cero en un dispositivo nuevo, que incluyen:

Abordar las denegaciones de servicios básicos

Las denegaciones generadas por los servicios básicos se tratan normalmente mediante el etiquetado de archivos. Por ejemplo:

avc: denied { open } for pid=1003 comm=”mediaserver” path="/dev/kgsl-3d0”
dev="tmpfs" scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0
tclass=chr_file permissive=1
avc: denied { read write } for pid=1003 name="kgsl-3d0" dev="tmpfs"
scontext=u:r:mediaserver:s0
tcontext=u:object_r:device:s0 tclass=chr_file permissive=1

se soluciona completamente etiquetando correctamente /dev/kgsl-3d0 . En este ejemplo, tcontext es device . Esto representa un contexto predeterminado donde todo en /dev recibe la etiqueta " dispositivo " a menos que se asigne una etiqueta más específica. Simplemente aceptar la salida de audit2allow aquí resultaría en una regla incorrecta y demasiado permisiva.

Para solucionar este tipo de problemas, asigne al archivo una etiqueta más específica, que en este caso es gpu_device . No se necesitan más permisos ya que el servidor de medias ya tiene los permisos necesarios en la política central para acceder a gpu_device.

Otros archivos específicos del dispositivo que deben etiquetarse con tipos predefinidos en la política principal:

En general, otorgar permisos a las etiquetas predeterminadas es incorrecto. Muchos de estos permisos no están permitidos por reglas bajas , pero incluso cuando no están explícitamente rechazados, la mejor práctica es proporcionar una etiqueta específica.

Etiquetar nuevos servicios y direcciones denegadas

Los servicios iniciados por init deben ejecutarse en sus propios dominios SELinux. El siguiente ejemplo coloca el servicio "foo" en su propio dominio SELinux y le otorga permisos.

El servicio se lanza en el init. device .rc nuestro dispositivo init. device .rc archivo init. device .rc como:

service foo /system/bin/foo
    class core
  1. Crea un nuevo dominio "foo"

    Cree el archivo device/ manufacturer / device-name /sepolicy/foo.te con el siguiente contenido:

    # foo service
    type foo, domain;
    type foo_exec, exec_type, file_type;
    
    init_daemon_domain(foo)
    

    Esta es la plantilla inicial para el dominio foo SELinux, al cual puede agregar reglas basadas en las operaciones específicas realizadas por ese ejecutable.

  2. Etiqueta /system/bin/foo

    Agregue lo siguiente a device/ manufacturer / device-name /sepolicy/file_contexts :

    /system/bin/foo   u:object_r:foo_exec:s0
    

    Esto asegura que el ejecutable esté correctamente etiquetado para que SELinux ejecute el servicio en el dominio adecuado.

  3. Cree y actualice las imágenes de arranque y del sistema.
  4. Refina las reglas de SELinux para el dominio.

    Utilice denegaciones para determinar los permisos necesarios. La herramienta audit2allow proporciona buenas pautas, pero solo úsela para informar la redacción de políticas. No se limite a copiar la salida.

Volver al modo de aplicación

Está bien solucionar problemas en modo permisivo, pero vuelva al modo de aplicación lo antes posible e intente permanecer allí.

Errores comunes

A continuación, se muestran algunas soluciones para errores comunes que ocurren al escribir políticas específicas para dispositivos.

Uso excesivo de la negación

La siguiente regla de ejemplo es como cerrar la puerta de entrada pero dejar las ventanas abiertas:

allow { domain -untrusted_app } scary_debug_device:chr_file rw_file_perms

La intención es clara: todos, excepto las aplicaciones de terceros, pueden tener acceso al dispositivo de depuración.

La regla tiene varios defectos. Es trivial evitar la exclusión de untrusted_app porque, opcionalmente, todas las aplicaciones pueden ejecutar servicios en el dominio isolated_app . Del mismo modo, si se agregan nuevos dominios para aplicaciones de terceros a AOSP, también tendrán acceso a scary_debug_device . La regla es demasiado permisiva. La mayoría de los dominios no se beneficiarán de tener acceso a esta herramienta de depuración. La regla debería haberse escrito para permitir solo los dominios que requieren acceso.

Funciones de depuración en producción

Las funciones de depuración no deben estar presentes en las compilaciones de producción ni tampoco su política.

La alternativa más simple es permitir la función de depuración solo cuando SELinux está deshabilitado en compilaciones eng / userdebug, como adb root y adb shell setenforce 0 .

Otra alternativa segura es incluir los permisos de depuración en una declaración userdebug_or_eng .

Explosión del tamaño de las políticas

Caracterizar las políticas de SEAndroid en la naturaleza describe una tendencia preocupante en el crecimiento de las personalizaciones de políticas de dispositivos. La política específica del dispositivo debe representar del 5 al 10% de la política general que se ejecuta en un dispositivo. Es casi seguro que las personalizaciones en el rango de más del 20% contienen más de dominios privilegiados y políticas muertas.

Política innecesariamente grande:

  • Tiene un doble impacto en la memoria, ya que la política se encuentra en el disco RAM y también se carga en la memoria del kernel.
  • Gasta espacio en disco al necesitar una imagen de arranque más grande.
  • Afecta a los tiempos de búsqueda de políticas de tiempo de ejecución.

El siguiente ejemplo muestra dos dispositivos en los que la política específica del fabricante comprendía el 50% y el 40% de la política del dispositivo. Una reescritura de la política produjo mejoras de seguridad sustanciales sin pérdida de funcionalidad, como se muestra a continuación. (Los dispositivos AOSP Shamu y Flounder se incluyen para comparar).

Figura 1: Comparación del tamaño de la política específica del dispositivo después de la auditoría de seguridad.

Figura 1 . Comparación del tamaño de la política específica del dispositivo después de la auditoría de seguridad.

En ambos casos, la política se redujo drásticamente tanto en tamaño como en número de permisos. La disminución en el tamaño de la política se debe casi en su totalidad a la eliminación de permisos innecesarios, muchos de los cuales probablemente fueron reglas generadas por audit2allow que se agregaron indiscriminadamente a la política. Los dominios muertos también fueron un problema para ambos dispositivos.

Otorgar la capacidad dac_override

Una denegación de dac_override significa que el proceso infractor está intentando acceder a un archivo con los permisos de usuario / grupo / mundo de Unix incorrectos. La solución adecuada casi nunca es otorgar el permiso dac_override . En su lugar, cambie los permisos de Unix en el archivo o proceso . Algunos dominios como init , vold e installd realmente necesitan la capacidad de anular los permisos de archivos de Unix para acceder a los archivos de otros procesos. Consulte el blog de Dan Walsh para obtener una explicación más detallada.