Personalizando SELinux

Después de haber integrado el nivel básico de la funcionalidad SELinux y haber analizado minuciosamente los resultados, puede agregar su propia configuración de política para cubrir sus personalizaciones en el sistema operativo Android. Estas políticas aún deben cumplir con los requisitos del programa de compatibilidad de Android y no deben eliminar la configuración predeterminada de SELinux.

Los fabricantes no deben eliminar la política SELinux existente. De lo contrario, corren el riesgo de romper la implementación de Android SELinux y las aplicaciones que gobierna. Esto incluye aplicaciones de terceros que probablemente deberán mejorarse para que sean compatibles y operativas. Las aplicaciones no deben requerir ninguna modificación para continuar funcionando en dispositivos habilitados para SELinux.

Al embarcarse en la personalización de SELinux, recuerde:

  • Escriba la política SELinux para todos los demonios nuevos.
  • Utilice dominios predefinidos cuando sea apropiado
  • Asigne un dominio a cualquier proceso generado como un servicio init
  • Familiarícese con las macros antes de redactar una política.
  • Enviar cambios a la política principal a AOSP

Y recuerda no:

  • Crear política incompatible
  • Permitir la personalización de políticas de usuario final
  • Permitir personalizaciones de políticas de MDM
  • Asustar a los usuarios con violaciones de políticas
  • Agregar puertas traseras

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

SELinux utiliza un enfoque de lista blanca, lo que significa que todo el acceso debe permitirse explícitamente en la política para poder ser concedido. Dado que la política SELinux predeterminada de Android ya es compatible con el Proyecto de código abierto de Android, no es necesario modificar la configuración de SELinux de ninguna manera. Si personaliza la configuración de SELinux, tenga mucho cuidado de no dañar las aplicaciones existentes. Para empezar:

  1. Utilice el último kernel de Android .
  2. Adoptar el principio de privilegio mínimo .
  3. Aborde solo sus propias adiciones a Android. La política predeterminada funciona automáticamente con el código base del proyecto de código abierto de Android .
  4. Compartimente los componentes de software en módulos que realicen tareas singulares.
  5. Cree políticas SELinux que aíslen esas tareas de funciones no relacionadas.
  6. Coloque esas políticas en archivos *.te (la extensión para los archivos fuente de políticas de SELinux) dentro del directorio /device/ manufacturer / device-name /sepolicy y use las variables BOARD_SEPOLICY para incluirlas en su compilación.
  7. Haga que los nuevos dominios sean permisivos inicialmente. Esto se hace mediante el uso de una declaración permisiva en el archivo .te del dominio.
  8. Analice los resultados y refine las definiciones de su dominio.
  9. Elimine la declaración permisiva cuando no aparezcan más denegaciones en las compilaciones de depuración del usuario.

Después de haber integrado el cambio de política de SELinux, agregue un paso a su flujo de trabajo de desarrollo para garantizar la compatibilidad de SELinux en el futuro. En un proceso de desarrollo de software ideal, la política de SELinux cambia sólo cuando cambia el modelo de software y no la implementación real.

Cuando comience a personalizar SELinux, primero audite sus adiciones a Android. Si agregó un componente que realiza una nueva función, asegúrese de que el componente cumpla con la política de seguridad de Android, así como con cualquier política asociada diseñada por el OEM, antes de activar el modo de aplicación.

Para evitar problemas innecesarios, es mejor ser demasiado amplio y compatible que demasiado restrictivo e incompatible, lo que da como resultado funciones rotas del dispositivo. Por el contrario, si sus cambios beneficiarán a otros, debe 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 será necesario realizar este cambio con cada nueva versión de Android.

Ejemplos de declaraciones de política

SELinux se basa en el lenguaje informático M4 y, por lo tanto, admite una variedad de macros para ahorrar tiempo.

En el siguiente ejemplo, a todos los dominios se les concede acceso para leer o escribir en /dev/null y leer desde /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 declaración se puede escribir con las macros SELinux *_file_perms (taquigrafía):

# 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;

Política de ejemplo

A continuación se muestra un ejemplo completo de política para DHCP, que examinamos 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 demonio DHCP hereda de la política de seguridad base ( domain ). Según 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 establece que DHCP se genera desde init y se le permite comunicarse con él.

En la línea net_domain(dhcp) , la política permite que DHCP utilice funciones de red comunes del dominio net , como leer y escribir paquetes TCP, comunicarse a través de sockets y realizar solicitudes DNS.

En la línea allow dhcp proc_net:file write; , la política establece que DHCP puede escribir en archivos específicos en /proc . Esta línea demuestra el etiquetado de archivos detallado de SELinux. Utiliza 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; Describe cómo se puede permitir que las aplicaciones interactúen entre sí. La política dice que DHCP y netd pueden comunicarse entre sí mediante descriptores de archivos, archivos FIFO, sockets de datagramas y sockets de flujo UNIX. DHCP sólo puede leer y escribir desde los sockets de datagramas y los sockets de flujo 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
enchufe
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
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 MÁS

nunca permitir reglas

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

Las siguientes pautas están destinadas a ayudar a los fabricantes a evitar errores relacionados con las reglas neverallow durante la personalización. Los números de regla utilizados 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;
Consulte la página de manual de ptrace . La capacidad sys_ptrace otorga la capacidad de ptrace cualquier proceso, lo que permite un gran control sobre otros procesos y debe pertenecer solo a los componentes designados del sistema, descritos en la regla. La necesidad de esta capacidad a menudo indica la presencia de algo que no está diseñado para compilaciones orientadas al usuario o una funcionalidad que no es necesaria. Retire 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. En concreto, afirma que sólo se ejecuta código en /system , lo que permite garantías de seguridad gracias a mecanismos como el arranque 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 .

Personalización de SEPolicy en Android 8.0+

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

Colocación de políticas

En Android 7.0 y versiones anteriores, los fabricantes de dispositivos podían agregar políticas a BOARD_SEPOLICY_DIRS , incluidas políticas destinadas a aumentar la política de 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 en AOSP:

  • sistema/sepolítica/público . Incluye la política exportada para su uso en la política específica del proveedor. Todo entra en la infraestructura de compatibilidad de Android 8.0. La política pública está destinada a persistir en todas las versiones para que pueda incluir cualquier cosa /public en su política personalizada. Debido a esto, el tipo de política que se puede colocar en /public es más restringido. Considere esto como la API de política exportada de la plataforma: todo lo que tenga que ver con la interfaz entre /system y /vendor pertenece aquí.
  • sistema/sepolítica/privado . Incluye la política necesaria para el funcionamiento de la imagen del sistema, pero de la cual la política de imagen del proveedor no debe tener conocimiento.
  • sistema/sepolicy/proveedor . Incluye una política para componentes que van en /vendor pero que existen en el árbol de la plataforma principal (no en directorios específicos del dispositivo). Este es un artefacto de la distinción del sistema de compilación entre dispositivos y componentes globales; Conceptualmente, esto es parte de la política específica del dispositivo que se describe a continuación.
  • dispositivo/ manufacturer / device-name /sepolicy . Incluye política específica del dispositivo. También incluye personalizaciones del dispositivo para la política, que en Android 8.0 y versiones posteriores corresponde a la política para los componentes en la imagen del proveedor.

En Android 11 y versiones posteriores, system_ext y las particiones de productos también pueden incluir políticas específicas de la partición. system_ext y las políticas de 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. Instalado 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 de la cual la política de imagen del proveedor no debe tener conocimiento. Instalado 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. Instalado 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 imagen del proveedor no debe tener conocimiento. Instalado en la partición del producto.
Nota: cuando se utiliza GSI, las particiones system_ext y de producto del OEM no se montarán. Las reglas en la política pública del proveedor que utiliza system_ext y la política pública del producto del OEM se convierten en NOP porque faltan las definiciones de tipo específicas del OEM.
Nota: Tenga mucho cuidado al utilizar system_ext y políticas públicas de productos. Las políticas públicas actúan como API exportada entre system_ext/product y el proveedor. Se supone que los socios deben gestionar ellos mismos los problemas de compatibilidad.

Escenarios de políticas admitidos

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

extensiones de solo imagen del proveedor

Ejemplo : agregar un nuevo servicio a vndservicemanager desde la imagen del proveedor que admita procesos de la imagen del proveedor.

Al igual que con los dispositivos que se lanzan con versiones anteriores de Android, agregue personalización específica del dispositivo en device/ manufacturer / device-name /sepolicy . La nueva política que rige cómo los componentes del proveedor interactúan con (solo) otros componentes del proveedor debe involucrar tipos presentes solo en device/ manufacturer / device-name /sepolicy . La política escrita aquí permite que funcione el código del proveedor, no se actualizará como parte de una OTA exclusiva del marco y estará presente en la política combinada en un dispositivo con la imagen del sistema AOSP de referencia.

soporte de imagen de proveedor para trabajar con AOSP

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

Al igual que con los dispositivos que se inician con versiones anteriores de Android, realice una 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 nuevas reglas que dictan las interacciones con los nuevos bits específicos del proveedor, sujeto a las restricciones neverallow proporcionadas. Al igual que en el caso exclusivo del proveedor, la nueva política aquí no se actualizará como parte de una OTA exclusiva del marco y estará presente en la política combinada en un dispositivo con la imagen del sistema AOSP de referencia.

extensiones de solo imagen del sistema

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

Agregue esta política a system/sepolicy/private . Puede agregar procesos u objetos adicionales para habilitar la funcionalidad en una imagen del sistema asociado, siempre que esos nuevos bits no necesiten interactuar con nuevos componentes en la imagen del proveedor (específicamente, dichos procesos u objetos deben funcionar completamente sin la política de la imagen del proveedor). . La política exportada por system/sepolicy/public está disponible aquí al igual que para las extensiones de solo imagen del proveedor. Esta política es parte de la imagen del sistema y podría actualizarse en una OTA solo de marco, pero no estará presente cuando se utilice la imagen del sistema AOSP de referencia.

extensiones de imagen de proveedor que sirven componentes AOSP extendidos

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

La política de interacción entre el sistema y el proveedor debe incluirse en el directorio device/ manufacturer / device-name /sepolicy enviado en la partición del proveedor. Esto es similar al escenario anterior de agregar soporte de imagen de proveedor para trabajar con la imagen AOSP de referencia, excepto que los componentes AOSP modificados también pueden requerir una política adicional para operar correctamente con el resto de la partición del sistema (lo cual está bien siempre y cuando todavía tienen las etiquetas de tipo AOSP públicas).

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

extensiones de imagen del sistema que acceden solo a interfaces AOSP

Ejemplo: un proceso de sistema nuevo que no es AOSP debe acceder a un HAL en el que se basa AOSP.

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

Extensiones de imagen de proveedor que sirven a nuevos componentes del sistema.

Ejemplo: agregar una nueva HAL que no sea AOSP para que la use un proceso cliente sin un análogo de AOSP (y, por lo tanto, requiere su propio dominio).

De manera similar al ejemplo de extensiones AOSP , la política para las interacciones entre el sistema y el proveedor debe ir en el directorio device/ manufacturer / device-name /sepolicy incluido en la partición del proveedor (para garantizar que la política del sistema no tenga conocimiento de los detalles específicos del proveedor). Puede agregar nuevos tipos públicos que extiendan la política en system/sepolicy/public ; Esto debe hacerse sólo además de la política AOSP existente, es decir, no eliminar la política pública AOSP. Los nuevos tipos públicos luego se pueden usar para políticas en system/sepolicy/private y en device/ manufacturer / device-name /sepolicy .

Tenga en cuenta que cada adición a system/sepolicy/public agrega complejidad al exponer una nueva garantía de compatibilidad que debe rastrearse en un archivo de mapeo y que está sujeta a otras restricciones. Sólo se pueden agregar nuevos tipos y las correspondientes reglas de permiso en system/sepolicy/public ; Los atributos y otras declaraciones de políticas no son compatibles. Además, los nuevos tipos públicos no se pueden utilizar para etiquetar objetos directamente en la política /vendor .

Escenarios de políticas no admitidos

Los dispositivos que se inician con Android 8.0 y versiones posteriores no son compatibles con los siguientes ejemplos y escenarios de políticas.

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

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

Similar a la interacción entre sistemas nuevos (no AOSP) y componentes de proveedores , excepto que el nuevo tipo de sistema se introduce en una OTA solo de marco. Aunque el nuevo tipo podría agregarse a la política en system/sepolicy/public , la política del proveedor existente no tiene conocimiento del nuevo tipo ya que solo rastrea la política pública del sistema Android 8.0. AOSP maneja 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 deberá ser proporcionado por un tipo público previamente existente.

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

La política sobre la imagen del sistema debe escribirse sin conocimiento de personalizaciones de proveedores específicos. Por lo tanto, la política relativa a interfaces específicas en AOSP se expone a través de atributos en system/sepolicy/public para que la política del proveedor pueda optar por una futura política del sistema que utilice estos atributos. Sin embargo, las extensiones de atributos en system/sepolicy/public no son compatibles , por lo que todas las políticas que dictan cómo interactúan los componentes del sistema con los componentes del nuevo proveedor (y que no son manejadas por atributos ya presentes en AOSP system/sepolicy/public ) deben estar en device/ manufacturer / device-name /sepolicy . Esto significa que los tipos de sistemas no pueden cambiar el acceso permitido a los tipos de proveedores como parte de una OTA exclusiva del marco.