Comprender los conceptos básicos de SELinux y cómo trabajar con él en Android
- AOSP: Abreviatura de Proyecto de código abierto de Android.
- AVC: Abreviatura de Access Vector Cache, la caché utilizada por SELinux para almacenar decisiones de control de acceso.
- comunicación: Abreviatura de comunicación.
- LSM: El acrónimo de Linux Security Modules, un marco que forma parte de Linux, permite el soporte para varias implementaciones de seguridad.
- MAC: Abreviatura de control de acceso obligatorio, un tipo de control de acceso a través del cual el sistema operativo limita la capacidad del iniciador para realizar una acción determinada.
- macros: Una instrucción que se extiende a un conjunto de instrucciones cuando se llama.
- NSA: Abreviatura de Agencia de Seguridad Nacional de los Estados Unidos.
- expresión regular: Abreviatura de expresión regular.
- contexto: Abreviatura de contexto de recursos, también conocido como dominio.
- SELinux: Abreviatura de Linux con mayor seguridad.
- Política de SELinux: Una política utilizada por SELinux que especifica un conjunto de permisos.
- SoC: Abreviatura de System on Chip.
- tclass: Abreviatura de clase objetivo.
- tcontext: Abreviatura de contexto del objetivo.
SELinux es un módulo del kernel de Linux que proporciona soporte de ejecución Control de acceso políticas de seguridad para hacer cumplir MAC. Se basa en el marco LSM.
SELinux fue desarrollado originalmente por NSA probar el valor MAC y cómo se puede aplicar a Linux. Se fusionó en Linux el 2 de agosto de 2003. gorra roja, McAfee Corp. es uno de los principales contribuyentes al desarrollo de SELinux. Más tarde llamó a un proyecto separado Mejoras de seguridad (SE) para Android fue dirigido por la NSA para integrar SELinux en Android. Este proyecto resultó en que SELinux fuera una parte esencial de Android. Se introdujo en Android 4.3 en modo tolerante, se aplicó parcialmente en Android 4.4, y desde Android 5.0 SELinux se ha aplicado completamente en Android.
SELinux puede funcionar en 2 modos, que son Aplicación y Tolerante. El modo predeterminado es Enforcing.
- En el modo de aplicación, SELinux aplica activamente una política que determina lo que está permitido (permisos en general). Si el iniciador desea realizar una acción, SELinux verifica si está permitido en la política y, si está permitido, solo entonces le permite realizar la acción solicitada. Si se niega, se escribirá en el búfer del kernel, que generalmente se puede leer dmesgy también en Android con logcat.
- En modo permisivo, SELinux solo registra información sobre una acción tomada por iniciadores que no estaba permitida en la política. No los limita.
Un ejemplo de un protocolo de rechazo de SELinux se ve así:
avc: denied { write } for comm="[email protected]" name="tp_double_tap" dev="proc" ino=4026533160 scontext=u:r:hal_power_default:s0 tcontext=u:object_r:proc:s0 tclass=file permissive=0
Los desarrolladores suelen utilizar el modo habilitado en las primeras etapas de un nuevo proyecto de Android, como un desarrollador que trabaja en una nueva versión de Android. Esto permite a los desarrolladores ahorrar tiempo durante las primeras etapas de desarrollo al registrar todas las políticas requeridas por varios procesos, servicios, firmware, etc., y resolverlos todos juntos una vez que el proyecto alcanza el nivel requerido de estabilidad.
Una política de SELinux es un conjunto de reglas (permisos) que especifican qué iniciador puede realizar qué tipo de acción. Si la acción específica que desea realizar no está explícitamente permitida en principio, SELinux la rechazará. Por lo tanto, en las instalaciones de producción, es de suma importancia tener un conjunto completo de reglas en la política de SELinux para evitar fallas / errores causados por SELinux. Las políticas de SELinux deben ser lo más estrictas posible para lograr la máxima seguridad. Uno debe recordar «Si no se rompe, no lo arregle» al escribir las políticas de SELinux.
De forma predeterminada, Android proporciona políticas SELinux para componentes específicos del sistema. Puedes encontrarlo almacenado en plataforma / sistema / sepolicy Almacenamiento AOSP. Las partes posteriores que realicen adiciones al AOSP para crear una ROM funcional deben escribir sus políticas de SELinux con respecto a los complementos, el enfoque que requieren. Por ejemplo, Qualcomm proporciona sepolicy para su SoC en dispositivo / qcom / sepolicy almacenamiento en sus servidores codeaurora. LineageOS proporciona a los desarrolladores sepolicy para sus complementos / funciones en AOSP v equipo / líneas / sepolicy almacenamiento alojado en LineageOS GitHub.
Todas estas diferentes reglas de políticas de SELinux se compilan juntas para generar políticas SELinux específicas para particiones de dispositivos. Por ejemplo, las reglas de política SELinux específicas del sistema terminan en la imagen del sistema, las reglas específicas de la partición del proveedor terminan en la imagen del proveedor, etc. Estas políticas específicas de la partición del dispositivo se compilan juntas en una sola política SELinux cuando Android se inicia y utilizado por SELinux.
La política de SELinux, como ya se ha dicho, es solo un conjunto de reglas. Escribir políticas SELinux significa escribir estas reglas, que pueden incluir permisos, designación (asignación de nombre) del iniciador, permitir que el iniciador se ejecute en modo tolerante, etc. Por lo tanto, escribir políticas SELinux se puede dividir en muchas partes más pequeñas relacionadas con el tipo de regla escrita.
Se utilizan muchos comandos al escribir políticas de SELinux. Sin embargo, dado el alcance del artículo, solo discutiremos declaraciones repetidas y básicas. Los administradores de dispositivos suelen utilizar estas declaraciones cuando escriben reglas de políticas SELinux específicas del dispositivo.
El primer paso es marcar al iniciador, si aún no lo ha hecho. Esto asegura que las autorizaciones otorgadas no conduzcan a un objetivo general, sino a uno específico. Como resultado, los iniciadores específicos tienen solo los permisos que necesitan para realizar una acción específica.
Designación del iniciador (no aplicación)
El plan es: /path/to/initiator/ u:object_r:context_name_you_want:s0
Un ejemplo de una regla de etiquetado NFC sería algo como: /(vendor|system/vendor)/bin/hw/[email protected] u:object_r:hal_nfc_default_exec:s0
Debe usar expresiones regulares para indicar el iniciador. Todas las etiquetas de archivo van a un archivo con nombre file_contexts. Por ejemplo, consulte el enlace plataforma / sistema / sepolicy / private / file_contexts.
Designación del iniciador (aplicación)
El plan es: user=user_of_app seinfo=info name=name_of_app domain=scontext_to_assign type=type_of_file
Un ejemplo de una regla para etiquetar una aplicación qtidataservices sería algo como: user=radio seinfo=platform name=.qtidataservices domain=qtidataservices_app type=radio_data_file
Todas las etiquetas de la aplicación van a un archivo con nombre seapp_contexts formateado según lo requiera la partición. Por ejemplo, consulte el enlace plataforma / sistema / sepolicy / private / seapp_contexts.
Etiquetado de sistemas de archivos
genfscon es un comando que se utiliza para asignar contextos a sistemas de archivos que no admiten ningún otro tipo de comando de etiquetado. El plan es: genfscon filesystem_name partial_path filesystem_context
Regla de muestra para etiquetado /proc/hwmodel
sería algo como: genfscon proc /hwmodel u:object_r:proc_fih:s0
Todos los comandos de genfscon van a un solo archivo llamado genfs_contexts. Por ejemplo, referencia, verifique plataforma / sistema / sepolicy / private / genfs_contexts.
Propiedades de etiquetado
Las propiedades son cadenas que controlan el comportamiento de una función en particular. Estás ubicado en .prop
archivos que se analizan init
al inicio del sistema. Estas propiedades también requieren que tenga un contexto SELinux válido para el iniciador que accederá a ellas.
El plan es: property_name u:object_r:property_type:s0
. Ejemplo de un protocolo de rechazo relacionado con los activos de la cámara:
avc: denied { set } for property=camera.tunning.live pid=756 uid=1047 gid=1005 scontext=u:r:hal_camera_default:s0 tcontext=u:object_r:default_prop:s0 tclass=property_service permissive=0
Esto debe abordarse designando esta propiedad en particular como camera_prop
porque tiene que ver con la camara camera.tunning.live u:object_r:camera_prop:s0
Todas las etiquetas de propiedad van a un archivo con nombre properties_contexts. Por ejemplo, consulte el enlace plataforma / sistema / sepolicy / master / private / property_contexts.
Observe cómo las declaraciones utilizadas para etiquetar servicios, procesos, aplicaciones y sistemas de archivos no terminan
;
a diferencia de otros comandos utilizados para otorgar o suprimir permisos. Una vez que el iniciador tiene una etiqueta, se le puede autorizar para realizar la acción requerida según sea necesario.
Permiso de permiso
Si desea permitir algunas acciones a los permisos de iniciador, puede usar allow
declaración. Se usa para otorgar permiso. El plan es: allow scontext tcontext:tclass permission;
Ejemplo en este caso particular:
avc: denied { read write } for pid=4565 comm="init.qcom.post_" name="read_ahead_kb" dev="sysfs" ino=52742 scontext=u:r:qti_init_shell:s0 tcontext=u:object_r:sysfs_dm:s0 tclass=file
El permiso sería: allow qti_init_shell sysfs_dm:file { read write };
Supresión del rechazo
Si sus registros contienen algunas denegaciones que desea ocultar / suprimir por algún motivo, puede usarlas dontaudit
declaración. El plan es: dontaudit scontext tcontext:tclass permission;
Ejemplo en este caso particular:
avc: denied { read } for comm="thermal-engine" name="kgsl" dev="sysfs" ino=29020 scontext=u:r:thermal-engine:s0 tcontext=u:object_r:sysfs:s0 tclass=dir permissive=0
La regla para suprimir este protocolo sería: dontaudit thermal-engine sysfs:dir read;
El AOSP recomienda mantener todas las reglas (autorización, denegación, supresión de protocolo, modo tolerante) para un iniciador específico en un archivo separado en .te un formato que tiene el nombre scontext. Por ejemplo, todas las reglas para un iniciador que tiene contexto hal_power_default se guardará en un archivo llamado hal_power_default.te. Por ejemplo, consulte el enlace plataforma / sistema / sepolicy / public / vold.te.
Nunca es una declaración que se utiliza para indicar reglas específicas que no se deben generar. Palabra generado indica que esta es una acción en tiempo de compilación, no una ejecución. Por lo tanto, si marca una regla específica como nunca baja y concede permiso para la misma regla en otra regla, el compilador arroja un error y detiene la compilación.
Regla de ejemplo: neverallow my_gallery my_secret_passwords:{ dir file } { read write open };
En Android, encontrará Neverallows dentro de la tienda del sistema. Android marca varias reglas como nunca permitidas, lo que potencialmente puede debilitar la seguridad del sistema. Por ejemplo, cada archivo del sistema tiene un tipo llamado system_data_fileAhora suponga que tiene un iniciador que quiere {leer escribir} acceso a un archivo específico que tiene system_data_file como tipo. Si ahora le otorga dicho permiso, significa que permite que el iniciador lea y escriba todos los archivos del sistema (porque todos los archivos del sistema tienen el mismo tipo de archivo). Esto debilita la seguridad. Por lo tanto, se marcaría como nunca permitir. La solución a este problema sería marcar el archivo en un contexto diferente y luego otorgar al iniciador los permisos requeridos.
Si bien, de forma predeterminada, varias reglas ya están marcadas como nunca bajas, no se cubren todas las posibles excepciones. Depende del desarrollador otorgar permiso cuidadosamente, teniendo en cuenta todos los escenarios. Por ejemplo, consulte el enlace plataforma / sistema / sepolicy / public / vold.te.
De forma predeterminada, hay varias macros disponibles al escribir políticas de SELinux. Estas macros no solo facilitan la escritura de políticas de SELinux, sino que también se recomiendan por varias razones, como otorgar una gran cantidad de permisos a un iniciador específico, otorgar un conjunto específico de permisos para una tarea específica al iniciador, etc. casos de uso y muchos otros beneficios.
Un ejemplo del uso de macros al escribir políticas de SELinux para habilitar permisos sería:
Ejemplo 1: Macros utilizadas: r_file_perms
Ningún fabricante: allow hal_power_default sysfs:file { read open watch lock };
Con macros: allow hal_power_default sysfs:file r_file_perms;
Ejemplo 2: Macros utilizadas: r_dir_file
Ningún fabricante: allow ueventd firmware_file:dir { open search };
y allow ueventd firmware_file:file { read getattr open };
Con macros: r_dir_file(ueventd, firmware_file)
Observe cómo el uso de macros reduce la cantidad de código y otorga el conjunto de permisos requerido. Puede comprobar las macros disponibles en global_macros y te_macros enviar plataforma / sistema / sepolicy Almacenamiento AOSP.
Hay varias herramientas útiles para ayudarlo a trabajar con SELinux y escribir políticas de SELinux. Algunos de ellos son:
- chcon: Ayuda a cambiar el contexto SELinux del objetivo.
- audit2allow: Genera políticas SELinux que contienen reglas de permitir y no auditar. Nunca incluye excepciones no autorizadas. audit2allow.perl alojado en OpenDarwin-CVS / SEDarwin es un script que no requiere dependencias externas y se ejecuta en cualquier plataforma a diferencia de las versiones modernas.
- restaurar: Restaura los contextos SELinux predeterminados del destino.
- sepolicy-inject: Las inserciones permiten reglas en las políticas binarias del kernel de SELinux.
La política de almacén de SELinux como referencia
Cada firmware / ROM base tiene una política SELinux dentro de imágenes de partición específicas. La ubicación general de la póliza es partition_name/etc/selinux/
. Esto significa que si está buscando políticas de imagen del sistema SELinux, estarían disponibles en /system/etc/selinux
, para la imagen del proveedor estaría en /vendor/etc/selinux
y así. Recuerde que la ruta a la partición varía mucho según el dispositivo. Un desarrollador puede usar esta política de acciones como referencia al escribir políticas de SELinux para su dispositivo específico. Esto no solo ayuda a acelerar la tarea de redactar reglas, sino que también sirve como referencia a qué regla se debe otorgar, cuál no, cómo tratar casos específicos, etc.
Tomé muchos enlaces de este sitio web. Creo que son realmente útiles, por eso los comparto a continuación. Échales un vistazo para obtener más información sobre SELinux para Android.
Este artículo no hubiera sido posible sin numerosas revisiones útiles de miembros del equipo de LineageOS, a saber: