Personaliza SELinux

Una vez que integres el nivel básico de la funcionalidad de SELinux y hayas analizado en detalle los resultados, puedes agregar tu propia configuración de política para cubrir tus personalizaciones del sistema operativo Android. Estas políticas aún deben cumplir con los requisitos del Programa de compatibilidad de Android y no deben quitar la configuración predeterminada de SELinux.

Los fabricantes no deben quitar la política de SELinux existente. De lo contrario, corren el riesgo de dañar la implementación de SELinux de Android y las apps que administra. Esto incluye las apps de terceros que probablemente deban mejorarse para cumplir con los requisitos y poder funcionar. Las apps no deben requerir ninguna modificación para seguir funcionando en dispositivos compatibles con SELinux.

Cuando comiences a personalizar SELinux, recuerda lo siguiente:

  • Se escribe la política de SELinux para todos los demonios nuevos.
  • Usa dominios predefinidos cuando sea apropiado
  • Asigna un dominio a cualquier proceso creado como servicio init
  • Familiarízate con las macros antes de escribir la política
  • Cómo enviar cambios de la política principal al AOSP

Y recuerda no hacer lo siguiente:

  • Crea una política incompatible
  • Permite la personalización de la política del usuario final
  • Permitir la personalización de la política de MDM
  • Asustar a los usuarios con incumplimientos de política
  • Agregar puertas traseras

Consulta la sección Funciones de seguridad del kernel del documento de definición de compatibilidad de Android para conocer los requisitos específicos.

SELinux usa un enfoque de lista de entidades permitidas, lo que significa que todo acceso debe permitirse explícitamente en la política para que se otorgue. Dado que la política predeterminada de SELinux de Android ya admite el Proyecto de código abierto de Android, no es necesario que modifiques la configuración de SELinux de ninguna manera. Si personalizas la configuración de SELinux, ten mucho cuidado de no dañar las apps existentes. Para comenzar, sigue estos pasos:

  1. Usa el kernel de Android más reciente.
  2. Adopta el principio de privilegio mínimo.
  3. Solo debes abordar tus propias incorporaciones a Android. La política predeterminada funciona automáticamente con la base de código del Proyecto de código abierto de Android.
  4. Compartimenta los componentes de software en módulos que realicen tareas únicas.
  5. Crea políticas de SELinux que aíslen esas tareas de funciones no relacionadas.
  6. Coloca esas políticas en archivos *.te (la extensión para los archivos de origen de políticas de SELinux) dentro del directorio /device/manufacturer/device-name/sepolicy y usa variables BOARD_SEPOLICY para incluirlas en tu compilación.
  7. Haz que los dominios nuevos sean permisivos inicialmente. Para ello, se usa una declaración permisiva en el archivo .te del dominio.
  8. Analiza los resultados y define mejor tus dominios.
  9. Quita la declaración permisiva cuando no aparezcan más rechazos en las compilaciones de userdebug.

Después de integrar el cambio de política de SELinux, agrega un paso al flujo de trabajo de desarrollo para garantizar la compatibilidad con SELinux en el futuro. En un proceso ideal de desarrollo de software, la política de SELinux cambia solo cuando cambia el modelo de software y no la implementación real.

Cuando comiences a personalizar SELinux, primero audita las incorporaciones a Android. Si agregaste un componente que ejecuta una función nueva, asegúrate de que cumpla con la política de seguridad de Android, así como con cualquier política asociada que cree el OEM, antes de activar el modo de aplicación forzosa.

Para evitar problemas innecesarios, es mejor ser demasiado amplio y compatible en lugar de ser demasiado restrictivo e incompatible, lo que da como resultado funciones del dispositivo dañadas. Por el contrario, si tus cambios beneficiarán a otras personas, debes enviar las modificaciones a la política predeterminada de SELinux como un parche. Si el parche se aplica a la política de seguridad predeterminada, no necesitarás realizar este cambio con cada versión nueva de Android.

Ejemplos de declaraciones de políticas

SELinux se basa en el lenguaje de programación M4 y, por lo tanto, admite una variedad de macros para ahorrar tiempo.

En el siguiente ejemplo, a todos los dominios se les otorga acceso para leer o escribir en /dev/null y leer en /dev/zero.

# Allow read / write access to /dev/null
allow domain null_device:chr_file { getattr open read ioctl lock append write};

# Allow read-only access to /dev/zero
allow domain zero_device:chr_file { getattr open read ioctl lock };

Esta misma sentencia se puede escribir con macros *_file_perms (abreviatura) de SELinux:

# Allow read / write access to /dev/null
allow domain null_device:chr_file rw_file_perms;

# Allow read-only access to /dev/zero
allow domain zero_device:chr_file r_file_perms;

Ejemplo de política

Este es un ejemplo completo de política para DHCP, que analizamos a continuación:

type dhcp, domain;
permissive dhcp;
type dhcp_exec, exec_type, file_type;
type dhcp_data_file, file_type, data_file_type;

init_daemon_domain(dhcp)
net_domain(dhcp)

allow dhcp self:capability { setgid setuid net_admin net_raw net_bind_service
};
allow dhcp self:packet_socket create_socket_perms;
allow dhcp self:netlink_route_socket { create_socket_perms nlmsg_write };
allow dhcp shell_exec:file rx_file_perms;
allow dhcp system_file:file rx_file_perms;
# For /proc/sys/net/ipv4/conf/*/promote_secondaries
allow dhcp proc_net:file write;
allow dhcp system_prop:property_service set ;
unix_socket_connect(dhcp, property, init)

type_transition dhcp system_data_file:{ dir file } dhcp_data_file;
allow dhcp dhcp_data_file:dir create_dir_perms;
allow dhcp dhcp_data_file:file create_file_perms;

allow dhcp netd:fd use;
allow dhcp netd:fifo_file rw_file_perms;
allow dhcp netd:{ dgram_socket_class_set unix_stream_socket } { read write };
allow dhcp netd:{ netlink_kobject_uevent_socket netlink_route_socket
netlink_nflog_socket } { read write };

Analicemos el ejemplo:

En la primera línea, la declaración de tipo, el daemon DHCP hereda de la política de seguridad base (domain). De los ejemplos de declaraciones anteriores, DHCP puede leer y escribir en /dev/null.

En la segunda línea, DHCP se identifica como un dominio permisivo.

En la línea init_daemon_domain(dhcp), la política indica que el DHCP se genera desde init y que puede comunicarse con él.

En la línea net_domain(dhcp), la política permite que DHCP use una funcionalidad de red común del dominio net, como leer y escribir paquetes de TCP, comunicarse a través de sockets y ejecutar solicitudes de DNS.

En la línea allow dhcp proc_net:file write;, la política indica que el DHCP puede escribir en archivos específicos en /proc. Esta línea demuestra el etiquetado detallado de archivos de SELinux. Usa la etiqueta proc_net para limitar el acceso de escritura solo a los archivos en /proc/sys/net.

El bloque final del ejemplo que comienza con allow dhcp netd:fd use; muestra cómo se puede permitir que las apps interactúen entre sí. La política indica que DHCP y netd pueden comunicarse entre sí a través de descriptores de archivos, archivos FIFO, sockets de datagramas y sockets de flujo de UNIX. DHCP solo puede leer y escribir en los sockets de datagramas y los sockets de flujo de UNIX, y no crearlos ni abrirlos.

Controles disponibles

Clase Permiso
archivo
ioctl read write create getattr setattr lock relabelfrom relabelto append
unlink link rename execute swapon quotaon mounton
directorio
add_name remove_name reparent search rmdir open audit_access execmod
zócalo
ioctl read write create getattr setattr lock relabelfrom relabelto append bind
connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg
name_bind
sistema de archivos
mount remount unmount getattr relabelfrom relabelto transition associate
quotamod quotaget
Proceso de creación del proyecto
fork transition sigchld sigkill sigstop signull signal ptrace getsched setsched
getsession getpgid setpgid getcap setcap share getattr setexec setfscreate
noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem
execstack execheap setkeycreate setsockcreate
seguridad
compute_av compute_create compute_member check_context load_policy
compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot
read_policy
capacidad
chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap
linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock
ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin
sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write
audit_control setfcap

MÁS

Y MUCHO MÁS

reglas neverallow

Las reglas neverallow de SELinux prohíben un comportamiento que nunca debería ocurrir. Con las pruebas de compatibilidad, las reglas neverallow de SELinux ahora se aplican en todos los dispositivos.

Los siguientes lineamientos están diseñados para ayudar a los fabricantes a evitar errores relacionados con las reglas neverallow durante la personalización. Los números de reglas que se usan aquí corresponden a Android 5.1 y están sujetos a cambios según la versión.

Regla 48: neverallow { domain -debuggerd -vold -dumpstate -system_server } self:capability sys_ptrace;
Consulta la página man de ptrace. La función sys_ptrace otorga la capacidad de ptrace cualquier proceso, lo que permite un gran control sobre otros procesos y debe pertenecer solo a componentes del sistema designados, que se describen en la regla. La necesidad de esta función suele indicar la presencia de algo que no está destinado a compilaciones para usuarios o funcionalidad que no es necesaria. Quita el componente innecesario.

Regla 76: neverallow { domain -appdomain -dumpstate -shell -system_server -zygote } { file_type -system_file -exec_type }:file execute;
Esta regla tiene como objetivo evitar la ejecución de código arbitrario en el sistema. Específicamente, afirma que solo se ejecuta el código en /system, lo que permite garantías de seguridad gracias a mecanismos como el inicio verificado. A menudo, la mejor solución cuando se encuentra un problema con esta regla neverallow es mover el código infractor a la partición /system.

Cómo personalizar SEPolicy en Android 8.0 y versiones posteriores

En esta sección, se proporcionan lineamientos para la política de SELinux del proveedor en Android 8.0 y versiones posteriores, incluidos detalles sobre SEPolicy y las extensiones de SEPolicy del Proyecto de código abierto de Android (AOSP). Para obtener más información sobre cómo se mantiene la compatibilidad de la política de SELinux entre particiones y versiones de Android, consulta Compatibilidad.

Posición de la política

En Android 7.0 y versiones anteriores, los fabricantes de dispositivos podían agregar una política a BOARD_SEPOLICY_DIRS, incluida una política destinada a aumentar la política del AOSP en diferentes tipos de dispositivos. En Android 8.0 y versiones posteriores, agregar una política a BOARD_SEPOLICY_DIRS coloca la política solo en la imagen del proveedor.

En Android 8.0 y versiones posteriores, la política existe en las siguientes ubicaciones del AOSP:

  • system/sepolicy/public. Incluye la política exportada para su uso en la política específica del proveedor. Todo se incluye en la infraestructura de compatibilidad de Android 8.0. La política pública está diseñada para persistir en todas las versiones, de modo que puedas incluir cualquier /public en tu política personalizada. Por este motivo, el tipo de política que se puede colocar en /public es más restrictivo. Considera esta API de política exportada de la plataforma: todo lo que se relacione con la interfaz entre /system y /vendor pertenece aquí.
  • system/sepolicy/private. Incluye la política necesaria para el funcionamiento de la imagen del sistema, pero de la que la política de imágenes del proveedor no debe tener conocimiento.
  • system/sepolicy/vendor. Incluye la política para los componentes que se incluyen en /vendor, pero que existen en el árbol de la plataforma principal (no en los directorios específicos del dispositivo). Este es un artefacto de la distinción del sistema de compilación entre dispositivos y componentes globales. Conceptualmente, es parte de la política específica del dispositivo que se describe a continuación.
  • device/manufacturer/device-name/sepolicy. Incluye la política específica del dispositivo. También incluye las personalizaciones de dispositivos de la política, que en Android 8.0 y versiones posteriores corresponde a la política para componentes de la imagen del proveedor.

En Android 11 y versiones posteriores, las particiones system_ext y del producto también pueden incluir políticas específicas de la partición. Las políticas de system_ext y del producto también se dividen en públicas y privadas, y los proveedores pueden usar las políticas públicas de system_ext y del producto, como la política del sistema.

  • SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS. Incluye la política exportada para su uso en la política específica del proveedor. Se instala en la partición system_ext.
  • SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS. Incluye la política necesaria para el funcionamiento de la imagen system_ext, pero la política de la imagen del proveedor no debe tener conocimiento de ella. Se instaló en la partición system_ext.
  • PRODUCT_PUBLIC_SEPOLICY_DIRS. Incluye la política exportada para su uso en la política específica del proveedor. Se instaló en la partición del producto.
  • PRODUCT_PRIVATE_SEPOLICY_DIRS. Incluye la política necesaria para el funcionamiento de la imagen del producto, pero de la que la política de imágenes del proveedor no debe tener conocimiento. Se instaló en la partición del producto.
Nota: Cuando se usa GSI, no se activarán system_ext ni las particiones de producto del OEM. Las reglas de la política de SE del proveedor que usan system_ext del OEM y la política pública del producto se convierten en NOP porque faltan las definiciones de tipo específicas del OEM.
Nota: Ten mucho cuidado cuando uses system_ext y las políticas públicas de productos. Las políticas públicas actúan como API exportada entre system_ext/product y el proveedor. Los socios deben gestionar los problemas de compatibilidad por su cuenta.

Situaciones de políticas admitidas

En los dispositivos que se inician con Android 8.0 y versiones posteriores, la imagen del proveedor debe funcionar con la imagen del sistema del OEM y la imagen de referencia del sistema AOSP que proporciona Google (y pasar la CTS en esta imagen de referencia). Estos requisitos garantizan una separación clara entre el framework y el código del proveedor. Estos dispositivos admiten las siguientes situaciones.

Extensiones solo de imagen para proveedores

Ejemplo: Agregar un servicio nuevo a vndservicemanager desde la imagen del proveedor que admite procesos desde la imagen del proveedor.

Al igual que con los dispositivos que se lanzan con versiones anteriores de Android, agrega la personalización específica del dispositivo en device/manufacturer/device-name/sepolicy. La nueva política que rige la forma en que los componentes del proveedor interactúan (solo) con otros componentes del proveedor debe incluir tipos presentes solo en device/manufacturer/device-name/sepolicy. La política que se escribió aquí permite que funcione el código del proveedor, no se actualizará como parte de una actualización inalámbrica solo de framework y está presente en la política combinada en un dispositivo con la imagen del sistema AOSP de referencia.

Compatibilidad con imágenes del proveedor para funcionar con AOSP

Ejemplo: Agregar un proceso nuevo (registrado con hwservicemanager desde la imagen del proveedor) que implemente un HAL definido por AOSP.

Al igual que con los dispositivos que se inician con versiones anteriores de Android, realiza la personalización específica del dispositivo en device/manufacturer/device-name/sepolicy. La política exportada como parte de system/sepolicy/public/ está disponible para su uso y se envía como parte de la política del proveedor. Los tipos y atributos de la política pública se pueden usar en reglas nuevas que dicten interacciones con los nuevos bits específicos del proveedor, sujeto a las restricciones de neverallow proporcionadas. Al igual que con el caso exclusivo del proveedor, la nueva política no se actualizará como parte de una OTA solo para el framework y está presente en la política combinada en un dispositivo con la imagen del sistema del AOSP de referencia.

Extensiones de solo imagen del sistema

Ejemplo: Agregar un servicio nuevo (registrado con servicemanager) al que solo pueden acceder otros procesos desde la imagen del sistema.

Agrega esta política a system/sepolicy/private. Puedes agregar procesos o objetos adicionales para habilitar la funcionalidad en una imagen del sistema de socios, siempre que esos bits nuevos no necesiten interactuar con componentes nuevos en la imagen del proveedor (específicamente, esos procesos o objetos deben funcionar por completo sin la política de la imagen del proveedor). La política que exporta system/sepolicy/public está disponible aquí, al igual que para las extensiones solo de imagen del proveedor. Esta política forma parte de la imagen del sistema y se puede actualizar en una actualización inalámbrica solo de framework, pero no estará presente cuando se use la imagen del sistema de referencia de AOSP.

Extensiones de imágenes del proveedor que entregan componentes de AOSP extendidos

Ejemplo: Un nuevo HAL que no es de AOSP para que lo usen los clientes extendidos que también existen en la imagen del sistema de AOSP (como un system_server extendido).

La política de interacción entre el sistema y el proveedor se debe incluir en el directorio device/manufacturer/device-name/sepolicy que se envía en la partición del proveedor. Esto es similar a la situación anterior de agregar compatibilidad con imágenes del proveedor para trabajar con la imagen de AOSP de referencia, excepto que los componentes de AOSP modificados también pueden requerir una política adicional para funcionar correctamente con el resto de la partición del sistema (lo cual está bien, siempre y cuando aún tengan las etiquetas de tipo AOSP públicas).

La política para la interacción de componentes públicos de AOSP con extensiones solo de imágenes del sistema debe estar en system/sepolicy/private.

extensiones de imágenes del sistema que solo acceden a interfaces de AOSP

Ejemplo: Un nuevo proceso del sistema que no sea del AOSP debe acceder a una HAL en la que se basa el AOSP.

Esto es similar al ejemplo de extensión de solo imagen del sistema, con la excepción de que los componentes nuevos del sistema pueden interactuar en la interfaz de system/vendor. La política del nuevo componente del sistema debe ir en system/sepolicy/private, lo cual es aceptable, siempre y cuando se realice a través de una interfaz que AOSP ya haya establecido en system/sepolicy/public (es decir, los tipos y atributos necesarios para la funcionalidad están allí). Si bien la política se puede incluir en la política específica del dispositivo, no podría usar otros tipos de system/sepolicy/private ni cambiar (de ninguna manera que afecte la política) como resultado de una actualización solo del framework. La política se puede cambiar en una actualización OTA solo de framework, pero no estará presente cuando se use una imagen del sistema AOSP (que tampoco tendrá el nuevo componente del sistema).

extensiones de imágenes del proveedor que publican nuevos componentes del sistema

Ejemplo: Agregar un nuevo HAL que no sea de AOSP para que lo use un proceso cliente sin un análogo de AOSP (por lo que requiere su propio dominio)

Al igual que en el ejemplo de extensiones del AOSP, la política para las interacciones entre el sistema y el proveedor debe ir en el directorio device/manufacturer/device-name/sepolicy enviado en la partición del proveedor (para garantizar que la política del sistema no tenga conocimiento de los detalles específicos del proveedor). Puedes agregar nuevos tipos públicos que extiendan la política en system/sepolicy/public. Esto solo debe hacerse en conjunto con la política del AOSP existente, es decir, no quitar la política pública del AOSP. Los nuevos tipos públicos se pueden usar para la política en system/sepolicy/private y en device/manufacturer/device-name/sepolicy.

Ten en cuenta que cada adición a system/sepolicy/public agrega complejidad, ya que expone una nueva garantía de compatibilidad de la que se debe hacer un seguimiento en un archivo de asignación y que está sujeta a otras restricciones. Solo se pueden agregar tipos nuevos y las reglas de permiso correspondientes en system/sepolicy/public. No se admiten atributos ni otras declaraciones de políticas. Además, los nuevos tipos públicos no se pueden usar para etiquetar directamente objetos en la política /vendor.

Situaciones de políticas no admitidas

Los dispositivos que se inician con Android 8.0 y versiones posteriores no admiten la siguiente situación ni los siguientes ejemplos de políticas.

Extensiones adicionales para la imagen del sistema que necesitan permiso para los nuevos componentes de imagen del proveedor después de una OTA solo para framework

Ejemplo: En la próxima versión de Android, se agrega un nuevo proceso del sistema que no es de AOSP, que requiere su propio dominio y necesita acceso a un nuevo HAL que no es de AOSP.

Es similar a la interacción entre los componentes del sistema y del proveedor nuevos (no AOSP), excepto que el nuevo tipo de sistema se presenta en una actualización OTA solo de framework. Aunque el tipo nuevo se podría agregar a la política en system/sepolicy/public, la política del proveedor existente no tiene conocimiento del tipo nuevo, ya que solo realiza un seguimiento de la política pública del sistema Android 8.0. AOSP controla esto exponiendo los recursos proporcionados por el proveedor a través de un atributo (por ejemplo, el atributo hal_foo), pero como las extensiones de socios de atributos no son compatibles con system/sepolicy/public, este método no está disponible para la política del proveedor. El acceso debe proporcionarse mediante un tipo público existente.

Ejemplo: Un cambio en un proceso del sistema (AOSP o no AOSP) debe cambiar la forma en que interactúa con un nuevo componente del proveedor que no es AOSP.

La política en la imagen del sistema se debe escribir sin conocer las personalizaciones específicas del proveedor. Por lo tanto, la política sobre interfaces específicas en AOSP se expone a través de atributos en system/sepolicy/public para que la política del proveedor pueda habilitar una política del sistema futura que use estos atributos. Sin embargo, las extensiones de atributos en system/sepolicy/public no son compatibles, por lo que todas las políticas que dicten cómo interactúan los componentes del sistema con los componentes nuevos del proveedor (y que no se manejan con atributos que ya están presentes en system/sepolicy/public de AOSP) deben estar en device/manufacturer/device-name/sepolicy. Esto significa que los tipos de sistema no pueden cambiar el acceso permitido a los tipos de proveedores como parte de una actualización OTA solo de framework.