En este artículo, se describe cómo Android controla los problemas de compatibilidad de políticas con las actualizaciones OTA de la plataforma, en las que la configuración de SELinux de la plataforma nueva puede diferir de la configuración de SELinux del proveedor anterior.
El diseño de políticas de SELinux basado en Treble considera una distinción binaria entre la política de plataforma y la de proveedor. El esquema se vuelve más complicado si las particiones del proveedor generan dependencias, como platform
< vendor
< oem
.
En Android 8.0 y versiones posteriores, la política global de SELinux se divide en componentes privados y públicos. Los componentes públicos consisten en la política y la infraestructura asociada, que se garantiza que estarán disponibles para una versión de la plataforma. Esta política se expondrá a los redactores de políticas de proveedores para permitir que los proveedores compilen un archivo de política de proveedor que, cuando se combina con la política proporcionada por la plataforma, genera una política completamente funcional para un dispositivo.
- Para el control de versiones, la política pública de la plataforma exportada se escribirá como atributos.
- Para facilitar la redacción de políticas, los tipos exportados se transformarán en atributos con versión como parte del proceso de compilación de políticas. Los tipos públicos también se pueden usar directamente en las decisiones de etiquetado que proporcionan los archivos de contexto del proveedor.
Android mantiene una asignación entre los tipos concretos exportados en la política de la plataforma y los atributos con versión correspondientes para cada versión de la plataforma. Esto garantiza que, cuando los objetos se etiquetan con un tipo, no se rompa el comportamiento garantizado por la política pública de la plataforma en una versión anterior. Para mantener esta asignación, se debe mantener actualizado un archivo de asignación para cada versión de la plataforma, que conserva la información de membresía de atributos para cada tipo exportado en la política pública.
Etiquetado y propiedad de objetos
Cuando se personaliza la política en Android 8.0 y versiones posteriores, la propiedad se debe definir de forma clara para cada objeto para mantener la política de la plataforma y del proveedor separadas. Por ejemplo, si el proveedor etiqueta /dev/foo
y, luego, la plataforma etiqueta /dev/foo
en una actualización OTA posterior, se producirá un comportamiento indefinido. En el caso de SELinux, esto se manifiesta como una colisión de etiquetado. El nodo del dispositivo puede tener solo una etiqueta que se resuelve en la etiqueta que se aplica por última vez. Resultado:
- Los procesos que necesitan acceso a la etiqueta aplicada de forma incorrecta perderán el acceso al recurso.
- Es posible que los procesos que obtienen acceso al archivo se interrumpan porque se creó el nodo de dispositivo incorrecto.
Las propiedades del sistema también pueden generar colisiones de nombres que podrían generar un comportamiento no definido en el sistema (así como en el etiquetado de SELinux). Pueden ocurrir colisiones entre las etiquetas de la plataforma y del proveedor para cualquier objeto que tenga una etiqueta de SELinux, incluidas las propiedades, los servicios, los procesos, los archivos y los sockets. Para evitar estos problemas, define claramente la propiedad de estos objetos.
Además de las colisiones de etiquetas, los nombres de tipos o atributos de SELinux también pueden colisionar. Una colisión de nombres de tipos o atributos siempre generará un error del compilador de políticas.
Espacios de nombres de tipos o atributos
SELinux no permite varias declaraciones del mismo tipo o atributo. La política con declaraciones duplicadas no se compilará. Para evitar colisiones de nombres de tipos y atributos, todas las declaraciones de proveedores deben tener un espacio de nombres que comience con vendor_
.
type foo, domain; → type vendor_foo, domain;
Propiedades del sistema y propiedad de etiquetado de procesos
La mejor manera de evitar las colisiones de etiquetado es usar espacios de nombres de propiedades. Para identificar fácilmente las propiedades de la plataforma y evitar conflictos de nombres cuando cambies el nombre de las propiedades de la plataforma exportada o agregues otras, asegúrate de que todas las propiedades del proveedor tengan sus propios prefijos:
Tipo de propiedad | Prefijos aceptables |
---|---|
propiedades de control | ctl.vendor. ctl.start$vendor. ctl.stop$vendor. init.svc.vendor.
|
de lectura y escritura | vendor. |
de solo lectura | ro.vendor. ro.boot. ro.hardware.
|
persistente | persist.vendor. |
Los proveedores pueden seguir usando ro.boot.*
(que proviene de la línea de comandos del kernel) y ro.hardware.*
(una propiedad relacionada con el hardware).
Todos los servicios del proveedor en los archivos init rc deben tener vendor.
para los servicios en los archivos init rc de particiones que no son del sistema. Se aplican reglas similares a las etiquetas de SELinux para las propiedades del proveedor (vendor_
para las propiedades del proveedor).
Propiedad de archivos
Evitar las colisiones de archivos es un desafío porque la política de la plataforma y del proveedor suelen proporcionar etiquetas para todos los sistemas de archivos. A diferencia del nombre de tipo, el espacio de nombres de los archivos no es práctico, ya que el kernel crea muchos de ellos. Para evitar estas colisiones, sigue las instrucciones de nombres de los sistemas de archivos que se indican en esta sección. En el caso de Android 8.0, estas son recomendaciones sin aplicación técnica. En el futuro, el conjunto de pruebas de proveedores (VTS) aplicará estas recomendaciones.
Sistema (/system)
Solo la imagen del sistema debe proporcionar etiquetas para los componentes /system
a través de file_contexts
, service_contexts
, etcétera. Si se agregan etiquetas para los componentes /system
en la política /vendor
, es posible que no se pueda realizar una actualización inalámbrica solo del framework.
Proveedor (/vendor)
La política de SELinux de AOSP ya etiqueta partes de la partición vendor
con las que interactúa la plataforma, lo que permite escribir reglas de SELinux para que los procesos de la plataforma puedan comunicarse o acceder a partes de la partición vendor
. Ejemplos:
Ruta de acceso /vendor |
Etiqueta proporcionada por la plataforma | Procesos de la plataforma según la etiqueta |
---|---|---|
/vendor(/.*)?
|
vendor_file
|
Todos los clientes de HAL en el framework, ueventd , etcétera
|
/vendor/framework(/.*)?
|
vendor_framework_file
|
dex2oat , appdomain , etcétera
|
/vendor/app(/.*)?
|
vendor_app_file
|
dex2oat , installd , idmap , etc.
|
/vendor/overlay(/.*)
|
vendor_overlay_file
|
system_server , zygote , idmap , etc.
|
Como resultado, se deben seguir reglas específicas (aplicadas a través de neverallows
) cuando se etiquetan archivos adicionales en la partición vendor
:
vendor_file
debe ser la etiqueta predeterminada para todos los archivos de la particiónvendor
. La política de la plataforma requiere esto para acceder a las implementaciones de HAL de transferencia.- Todos los
exec_types
nuevos agregados en la particiónvendor
a través de SEPolicy del proveedor deben tener el atributovendor_file_type
. Esto se aplica a través de neverallows. - Para evitar conflictos con futuras actualizaciones de la plataforma o el framework, evita etiquetar archivos que no sean
exec_types
en la particiónvendor
. - Todas las dependencias de bibliotecas para los HAL de mismo proceso identificados por AOSP deben etiquetarse como
same_process_hal_file.
.
Procfs (/proc)
Los archivos de /proc
se pueden etiquetar solo con la etiqueta genfscon
. En Android 7.0, tanto la política de la plataforma como la del proveedor usaban genfscon
para etiquetar archivos en procfs
.
Recomendación: Solo etiqueta /proc
con la política de la plataforma.
Si los procesos de vendor
necesitan acceso a archivos en /proc
que actualmente están etiquetados con la etiqueta predeterminada (proc
), la política del proveedor no debe etiquetarlos de forma explícita y, en su lugar, debe usar el tipo genérico proc
para agregar reglas para los dominios del proveedor. Esto permite que las actualizaciones de la plataforma se adapten a las futuras interfaces de kernel expuestas a través de procfs
y las etiqueten de forma explícita según sea necesario.
Debugfs (/sys/kernel/debug)
Debugfs
se puede etiquetar en file_contexts
y genfscon
. En Android 7.0 a Android 10, tanto la plataforma como el proveedor etiquetan debugfs
.
En Android 11, no se puede acceder a debugfs
ni activarlo en dispositivos de producción. Los fabricantes de dispositivos deben quitar debugfs
.
Tracefs (/sys/kernel/debug/tracing)
Tracefs
se puede etiquetar en file_contexts
y genfscon
. En Android 7.0, solo la plataforma etiqueta tracefs
.
Recomendación: Solo la plataforma puede etiquetar tracefs
.
Sysfs (/sys)
Los archivos en /sys
se pueden etiquetar con file_contexts
y genfscon
. En Android 7.0, tanto la plataforma como el proveedor usan genfscon
para etiquetar archivos en sysfs
.
Recomendación: La plataforma puede etiquetar nodos sysfs
que no son específicos del dispositivo. De lo contrario, solo el proveedor puede etiquetar archivos.
tmpfs (/dev)
Los archivos de /dev
pueden estar etiquetados en file_contexts
. En Android 7.0, se incluyen los archivos de etiquetas de la plataforma y del proveedor.
Recomendación: El proveedor solo puede etiquetar archivos en /dev/vendor
(por ejemplo, /dev/vendor/foo
, /dev/vendor/socket/bar
).
Rootfs (/)
Los archivos de /
pueden estar etiquetados en file_contexts
. En Android 7.0, se incluyen los archivos de etiquetas de la plataforma y del proveedor.
Recomendación: Solo el sistema puede etiquetar archivos en /
.
Datos (/data)
Los datos se etiquetan a través de una combinación de file_contexts
y seapp_contexts
.
Recomendación: No permitas el etiquetado de proveedores fuera de /data/vendor
. Solo la plataforma puede etiquetar otras partes de /data
.
Versión de etiquetas de Genfs
A partir del nivel de API del proveedor 202504, las etiquetas de SELinux más recientes asignadas con genfscon
en system/sepolicy/compat/plat_sepolicy_genfs_{ver}.cil
son opcionales para las particiones de proveedores más antiguas. Esto permite que las particiones de proveedores más antiguas conserven su implementación de SEPolicy existente. Esto se controla mediante la variable BOARD_GENFS_LABELS_VERSION
de Makefile, que se almacena en /vendor/etc/selinux/genfs_labels_version.txt
.
Ejemplo:
-
En el nivel de API del proveedor 202404, el nodo
/sys/class/udc
se etiqueta comosysfs
de forma predeterminada. -
A partir del nivel de API del proveedor 202504,
/sys/class/udc
se etiqueta comosysfs_udc
.
Sin embargo, es posible que las particiones del proveedor usen /sys/class/udc
con el nivel de API 202404, ya sea con la etiqueta sysfs
predeterminada o con una etiqueta específica del proveedor. Etiquetar /sys/class/udc
como sysfs_udc
de forma incondicional podría romper la compatibilidad con estas particiones de proveedores. Cuando se verifica BOARD_GENFS_LABELS_VERSION
, la plataforma sigue usando las etiquetas y los permisos anteriores para las particiones de proveedores más antiguas.
BOARD_GENFS_LABELS_VERSION
puede ser mayor o igual que el nivel de API del proveedor. Por ejemplo, las particiones de proveedores que usan el nivel de API 202404 pueden establecer BOARD_GENFS_LABELS_VERSION
en 202504 para adoptar las etiquetas nuevas que se introdujeron en 202504. Consulta la lista de
etiquetas de genfs específicas de 202504.
Cuando se etiquetan los nodos genfscon
, la plataforma debe considerar las particiones de proveedores más antiguas y, cuando sea necesario, implementar mecanismos de resguardo para la compatibilidad. La plataforma puede usar bibliotecas solo para la plataforma para consultar la versión de etiquetas de genfs.
-
En nativo, usa
libgenfslabelsversion
. Consultagenfslabelsversion.h
para ver el archivo de encabezado delibgenfslabelsversion
. -
En Java, usa
android.os.SELinux.getGenfsLabelsVersion()
.
Atributos de compatibilidad
La política de SELinux es una interacción entre los tipos de origen y destino para clases y permisos de objetos específicos. Cada objeto (procesos, archivos, etc.) afectado por la política de SELinux puede tener un solo tipo, pero ese tipo puede tener varios atributos.
La política se escribe principalmente en términos de los tipos existentes:
allow source_type target_type:target_class permission(s);
Esto funciona porque la política se escribió con conocimiento de todos los tipos. Sin embargo, si la política del proveedor y la política de la plataforma usan tipos específicos, y la etiqueta de un objeto específico cambia en solo una de esas políticas, la otra puede contener una política que ganó o perdió el acceso al que se recurría anteriormente. Por ejemplo:
File_contexts: /sys/A u:object_r:sysfs:s0 Platform: allow p_domain sysfs:class perm; Vendor: allow v_domain sysfs:class perm;
Se podría cambiar a lo siguiente:
File_contexts: /sys/A u:object_r:sysfs_A:s0
Aunque la política del proveedor seguiría siendo la misma, v_domain
perdería el acceso debido a la falta de política para el nuevo tipo sysfs_A
.
Cuando definimos una política en términos de atributos, podemos darle al objeto subyacente un tipo que tenga un atributo correspondiente a la política para la plataforma y el código del proveedor. Esto se puede hacer para todos los tipos para crear de manera eficaz una política de atributos en la que nunca se usen tipos concretos. En la práctica, esto solo es obligatorio para las partes de la política que se superponen entre la plataforma y el proveedor, que se definen y proporcionan como política pública de la plataforma que se compila como parte de la política del proveedor.
Definir la política pública como atributos con control de versión satisface dos objetivos de compatibilidad de políticas:
- Asegúrate de que el código del proveedor siga funcionando después de la actualización de la plataforma. Esto se logra agregando atributos a tipos concretos para objetos que corresponden a aquellos en los que se basaba el código del proveedor, lo que preserva el acceso.
- Capacidad de dar de baja la política. Para ello, se deben definir claramente los conjuntos de políticas en atributos que se puedan quitar en cuanto ya no se admita la versión a la que corresponden. El desarrollo puede continuar en la plataforma, ya que la política anterior aún está presente en la política del proveedor y se quitará automáticamente cuando se actualice.
Capacidad de escritura de políticas
Para cumplir con el objetivo de no requerir conocimiento de cambios de versión específicos para el desarrollo de políticas, Android 8.0 incluye una asignación entre los tipos de políticas públicas de la plataforma y sus atributos. El tipo foo
se asigna al atributo foo_vN
, en el que N
es la versión objetivo. vN
corresponde a la variable de compilación PLATFORM_SEPOLICY_VERSION
y tiene el formato MM.NN
, en el que MM
corresponde al número de SDK de la plataforma y NN
es una versión específica de la política de seguridad de la plataforma.
Los atributos de la política pública no tienen control de versiones, sino que existen como una API en la que se pueden compilar la política de la plataforma y del proveedor para mantener estable la interfaz entre las dos particiones. Los redactores de políticas de la plataforma y de los proveedores pueden seguir redactando las políticas tal como están redactadas en la actualidad.
La política pública de la plataforma exportada como allow source_foo target_bar:class
perm;
se incluye como parte de la política del proveedor. Durante la compilación (que incluye la versión correspondiente), se transforma en la política que irá a la parte del proveedor del dispositivo (que se muestra en el lenguaje intermedio común (CIL) transformado):
(allow source_foo_vN target_bar_vN (class (perm)))
Como la política del proveedor nunca está por delante de la plataforma, no debería preocuparse por las versiones anteriores. Sin embargo, la política de la plataforma deberá saber qué tan antigua es la política del proveedor, incluir atributos a sus tipos y establecer la política correspondiente a los atributos con versión.
Diferencias entre políticas
Si agregas _vN
al final de cada tipo para crear atributos automáticamente, no se hará nada sin asignar atributos a tipos en las diferencias de versiones. Android mantiene una asignación entre las versiones de los atributos y una asignación de tipos a esos atributos. Esto se hace en los archivos de asignación
antes mencionados con instrucciones, como (CIL):
(typeattributeset foo_vN (foo))
Actualizaciones de la plataforma
En la siguiente sección, se detallan las situaciones de las actualizaciones de la plataforma.
Mismos tipos
Esta situación ocurre cuando un objeto no cambia las etiquetas en las versiones de políticas.
Esto es lo mismo para los tipos de origen y destino, y se puede ver con /dev/binder
, que se etiqueta como binder_device
en todas las versiones. Se representa en la política transformada de la siguiente manera:
binder_device_v1 … binder_device_vN
Cuando se actualiza de v1
a v2
, la política de la plataforma debe contener lo siguiente:
type binder_device; -> (type binder_device) (in CIL)
En el archivo de asignación de v1 (CIL):
(typeattributeset binder_device_v1 (binder_device))
En el archivo de asignación v2 (CIL), haz lo siguiente:
(typeattributeset binder_device_v2 (binder_device))
En la política de proveedores de la versión 1 (CIL):
(typeattribute binder_device_v1) (allow binder_device_v1 …)
En la política de proveedores de la versión 2 (CIL):
(typeattribute binder_device_v2) (allow binder_device_v2 …)
Tipos nuevos
Esta situación ocurre cuando la plataforma agregó un tipo nuevo, lo que puede suceder cuando se agregan funciones nuevas o durante el endurecimiento de la política.
- Función nueva. Cuando el tipo etiqueta un objeto que antes no existía (como un nuevo proceso de servicio), el código del proveedor no interactuaba con él directamente, por lo que no existe una política correspondiente. El atributo nuevo que corresponde al tipo no tiene un atributo en la versión anterior, por lo que no necesitaría una entrada en el archivo de asignación segmentada para esa versión.
- Endurecimiento de la política Cuando el tipo representa el endurecimiento de la política, el atributo de tipo nuevo debe vincularse a una cadena de atributos que corresponda al anterior (similar al ejemplo anterior en el que se cambia
/sys/A
desysfs
asysfs_A
). El código del proveedor se basa en una regla que habilita el acceso asysfs
y debe incluir esa regla como un atributo del tipo nuevo.
Cuando se actualiza de v1
a v2
, la política de la plataforma debe contener lo siguiente:
type sysfs_A; -> (type sysfs_A) (in CIL) type sysfs; (type sysfs) (in CIL)
En el archivo de asignación de v1 (CIL):
(typeattributeset sysfs_v1 (sysfs sysfs_A))
En el archivo de asignación v2 (CIL), haz lo siguiente:
(typeattributeset sysfs_v2 (sysfs)) (typeattributeset sysfs_A_v2 (sysfs_A))
En la política de proveedores de la versión 1 (CIL):
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
En la política de proveedores de la versión 2 (CIL):
(typeattribute sysfs_A_v2) (allow … sysfs_A_v2 …) (typeattribute sysfs_v2) (allow … sysfs_v2 …)
Tipos quitados
Esta situación (rara) ocurre cuando se quita un tipo, lo que puede suceder cuando el objeto subyacente hace lo siguiente:
- Permanece, pero recibe una etiqueta diferente.
- La plataforma lo quita.
Durante la flexibilización de la política, se quita un tipo y se le asigna al objeto etiquetado con ese tipo una etiqueta diferente que ya existe. Esto representa una combinación de asignaciones de atributos: el código del proveedor aún debe poder acceder al objeto subyacente por el atributo que solía tener, pero el resto del sistema ahora debe poder acceder a él con su atributo nuevo.
Si el atributo al que se cambió es nuevo, el cambio de etiqueta es el mismo que en el caso del tipo nuevo, excepto que, cuando se usa una etiqueta existente, la adición del tipo nuevo del atributo anterior haría que otros objetos también etiquetados con este tipo sean accesibles. Esto es, en esencia, lo que hace la plataforma y se considera una compensación aceptable para mantener la compatibilidad.
(typeattribute sysfs_v1) (allow … sysfs_v1 …)
Ejemplo de la versión 1: Tipos de colapso (quitar sysfs_A)
Cuando se actualiza de v1
a v2
, la política de la plataforma debe contener lo siguiente:
type sysfs; (type sysfs) (in CIL)
En el archivo de asignación de v1 (CIL):
(typeattributeset sysfs_v1 (sysfs)) (type sysfs_A) # in case vendors used the sysfs_A label on objects (typeattributeset sysfs_A_v1 (sysfs sysfs_A))
En el archivo de asignación v2 (CIL), haz lo siguiente:
(typeattributeset sysfs_v2 (sysfs))
En la política de proveedores de la versión 1 (CIL):
(typeattribute sysfs_A_v1) (allow … sysfs_A_v1 …) (typeattribute sysfs_v1) (allow … sysfs_v1 …)
En la política de proveedores de la versión 2 (CIL):
(typeattribute sysfs_v2) (allow … sysfs_v2 …)
Ejemplo de versión 2: Eliminación completa (tipo foo)
Cuando se actualiza de v1
a v2
, la política de la plataforma debe contener lo siguiente:
# nothing - we got rid of the type
En el archivo de asignación de v1 (CIL):
(type foo) #needed in case vendors used the foo label on objects (typeattributeset foo_v1 (foo))
En el archivo de asignación v2 (CIL), haz lo siguiente:
# nothing - get rid of it
En la política de proveedores de la versión 1 (CIL):
(typeattribute foo_v1) (allow foo …) (typeattribute sysfs_v1) (allow sysfs_v1 …)
En la política de proveedores de la versión 2 (CIL):
(typeattribute sysfs_v2) (allow sysfs_v2 …)
Nueva clase o permisos
Esta situación ocurre cuando una actualización de la plataforma introduce nuevos componentes de políticas que no existen en versiones anteriores. Por ejemplo, cuando Android agregó el administrador de objetos servicemanager
que creó los permisos de agregar, buscar y enumerar, los demonios del proveedor que querían registrarse con los permisos necesarios de servicemanager
no estaban disponibles. En Android 8.0, solo la política de la plataforma puede agregar clases y permisos nuevos.
Para permitir que todos los dominios que podrían haberse creado o extendido con la política del proveedor usen la clase nueva sin obstrucciones, la política de la plataforma debe incluir una regla similar a la siguiente:
allow {domain -coredomain} *:new_class perm;
Es posible que incluso se requiera una política que permita el acceso para todos los tipos de interfaz (política pública) para asegurarse de que la imagen del proveedor obtenga acceso. Si esto genera una política de seguridad inaceptable (como podría suceder con los cambios de servicemanager), es posible que se deba forzar una actualización del proveedor.
Se quitaron la clase o los permisos
Esta situación ocurre cuando se quita un administrador de objetos (como el administrador de objetos ZygoteConnection
) y no debería causar problemas. La clase y los permisos del administrador de objetos podrían permanecer definidos en la política hasta que la versión del proveedor ya no los use. Para ello, agrega las definiciones
al archivo de asignación correspondiente.
Personalización del proveedor para tipos nuevos o con nueva etiqueta
Los nuevos tipos de proveedores son fundamentales para el desarrollo de las políticas de proveedores, ya que son necesarios para describir procesos, objetos binarios, dispositivos, subsistemas y datos almacenados nuevos. Por lo tanto, es fundamental permitir la creación de tipos definidos por el proveedor.
Como la política del proveedor siempre es la más antigua del dispositivo, no es necesario convertir automáticamente todos los tipos de proveedores en atributos en la política. La plataforma no se basa en nada etiquetado en la política del proveedor porque no la conoce. Sin embargo, proporcionará los atributos y los tipos públicos que usa para interactuar con objetos etiquetados con estos tipos (como domain
, sysfs_type
, etcétera). Para que la plataforma siga interactuando correctamente con estos objetos, los atributos y tipos deben aplicarse de forma adecuada, y es posible que debas agregar reglas específicas a los dominios personalizables (como init
).
Cambios de atributos para Android 9
Los dispositivos que se actualizan a Android 9 pueden usar los siguientes atributos, pero los dispositivos que se inician con Android 9 no deben hacerlo.
Atributos del infractor
Android 9 incluye los siguientes atributos relacionados con el dominio:
data_between_core_and_vendor_violators
. Atributo para todos los dominios que incumplen el requisito de no compartir archivos por ruta de acceso entrevendor
ycoredomains
. Los procesos de la plataforma y del proveedor no deben usar archivos en el disco para comunicarse (ABI inestable). Recomendación:- El código del proveedor debe usar
/data/vendor
. - El sistema no debe usar
/data/vendor
.
- El código del proveedor debe usar
system_executes_vendor_violators
. Es un atributo para todos los dominios del sistema (exceptoinit
yshell domains
) que incumplen el requisito de no ejecutar objetos binarios del proveedor. La ejecución de objetos binarios del proveedor tiene una API inestable. La plataforma no debe ejecutar los objetos binarios del proveedor directamente. Recomendación:- Estas dependencias de la plataforma en los objetos binarios del proveedor deben estar detrás de los HAL de HIDL.
O BIEN
- Los
coredomains
que necesitan acceso a los objetos binarios del proveedor deben trasladarse a la partición del proveedor y, por lo tanto, dejar de sercoredomain
.
- Estas dependencias de la plataforma en los objetos binarios del proveedor deben estar detrás de los HAL de HIDL.
Atributos no confiables
Las apps no confiables que alojan código arbitrario no deben tener acceso a los servicios de HwBinder, excepto aquellos que se consideran lo suficientemente seguros para el acceso desde esas apps (consulta los servicios seguros a continuación). Estos son los dos motivos principales:
- Los servidores de HwBinder no realizan la autenticación del cliente porque, actualmente, HIDL no expone la información del UID del llamador. Incluso si HIDL expusiera esos datos, muchos servicios de HwBinder operan en un nivel inferior al de las apps (como los HAL) o no deben depender de la identidad de la app para la autorización. Por lo tanto, para mayor seguridad, la suposición predeterminada es que cada servicio de HwBinder trata a todos sus clientes como igualmente autorizados para realizar las operaciones que ofrece el servicio.
- Los servidores HAL (un subconjunto de servicios de HwBinder) contienen código con una tasa de incidencia más alta de problemas de seguridad que los componentes
system/core
y tienen acceso a las capas inferiores de la pila (hasta el hardware), lo que aumenta las oportunidades para eludir el modelo de seguridad de Android.
Servicios seguros
Entre los servicios seguros, se incluyen los siguientes:
same_process_hwservice
. Estos servicios (por definición) se ejecutan en el proceso del cliente y, por lo tanto, tienen el mismo acceso que el dominio del cliente en el que se ejecuta el proceso.coredomain_hwservice
. Estos servicios no representan riesgos asociados con el motivo 2.hal_configstore_ISurfaceFlingerConfigs
. Este servicio está diseñado específicamente para que lo use cualquier dominio.hal_graphics_allocator_hwservice
. El servicio de Bindersurfaceflinger
también ofrece estas operaciones, a las que las apps pueden acceder.hal_omx_hwservice
: Esta es una versión de HwBinder del servicio de Bindermediacodec
al que las apps pueden acceder.hal_codec2_hwservice
. Esta es una versión más reciente dehal_omx_hwservice
.
Atributos utilizables
Todos los hwservices
que no se consideran seguros tienen el atributo untrusted_app_visible_hwservice
. Los servidores HAL correspondientes tienen el atributo untrusted_app_visible_halserver
. Los dispositivos que se lanzan con Android 9 NO DEBEN usar ninguno de los atributos untrusted
.
Recomendación:
- En cambio, las apps no confiables deben comunicarse con un servicio del sistema que se comunique con el HAL de HIDL del proveedor. Por ejemplo, las apps pueden comunicarse con
binderservicedomain
y, luego,mediaserver
(que es unbinderservicedomain
) a su vez se comunica conhal_graphics_allocator
.O BIEN
- Las apps que necesitan acceso directo a los HAL de
vendor
deben tener su propio dominio de política de seguridad definido por el proveedor.
Pruebas de atributos de archivos
Android 9 incluye pruebas de tiempo de compilación que garantizan que todos los archivos en ubicaciones específicas tengan los atributos apropiados (por ejemplo, que todos los archivos en sysfs
tengan el atributo sysfs_type
requerido).
Política pública de la plataforma
La política pública de la plataforma es el núcleo de la conformidad con el modelo de arquitectura de Android 8.0 sin simplemente mantener la unión de las políticas de la plataforma de la v1 y la v2. Los proveedores están expuestos a un subconjunto de la política de la plataforma que contiene tipos y atributos utilizables, y reglas sobre esos tipos y atributos que, luego, se convierten en parte de la política del proveedor (es decir, vendor_sepolicy.cil
).
Los tipos y las reglas se traducen automáticamente en la política generada por el proveedor a attribute_vN
, de modo que todos los tipos proporcionados por la plataforma sean atributos con control de versiones (sin embargo, los atributos no tienen control de versiones). La plataforma es responsable de asignar los tipos concretos que proporciona a los atributos adecuados para garantizar que la política del proveedor siga funcionando y que se incluyan las reglas proporcionadas para una versión en particular. La combinación de la política pública de la plataforma y la política del proveedor satisface el objetivo del modelo de arquitectura de Android 8.0 de permitir compilaciones independientes de la plataforma y del proveedor.
Asignación a cadenas de atributos
Cuando se usan atributos para asignarlos a versiones de políticas, un tipo se asigna a un atributo o a varios, lo que garantiza que se pueda acceder a los objetos etiquetados con el tipo a través de los atributos correspondientes a sus tipos anteriores.
Mantener un objetivo para ocultar la información de la versión al escritor de políticas significa generar automáticamente los atributos con control de versiones y asignarlos a los tipos adecuados. En el caso común de los tipos estáticos, esto es sencillo: type_foo
se asigna a type_foo_v1
.
Para un cambio de etiqueta de objeto, como sysfs
→ sysfs_A
o mediaserver
→ audioserver
, crear esta asignación no es trivial (y se describe en los ejemplos anteriores). Los encargados de mantener las políticas de la plataforma deben determinar cómo crear la asignación en los puntos de transición de los objetos, lo que requiere comprender la relación entre los objetos y sus etiquetas asignadas, y determinar cuándo ocurre esto. Para la retrocompatibilidad, esta complejidad se debe administrar en el lado de la plataforma, que es la única partición que puede actualizarse.
Versiones anteriores
Para simplificar, la plataforma de Android lanza una versión de sepolicy cuando se corta una nueva
rama de lanzamiento. Como se describió anteriormente, el número de versión se encuentra en PLATFORM_SEPOLICY_VERSION
y tiene el formato MM.nn
, donde MM
corresponde al valor del SDK y nn
es un valor privado que se mantiene en /platform/system/sepolicy.
. Por ejemplo, 19.0
para Kitkat, 21.0
para Lollipop, 22.0
para Lollipop-MR1, 23.0
para Marshmallow, 24.0
para Nougat, 25.0
para Nougat-MR1, 26.0
para Oreo, 27.0
para Oreo-MR1 y 28.0
para Android 9.
Los valores de Uprev no siempre son números enteros. Por ejemplo, si un aumento de MR a una versión requiere un cambio incompatible en system/sepolicy/public
, pero no un aumento de API, esa versión de sepolicy podría ser vN.1
. La versión presente en una rama de desarrollo es una 10000.0
que nunca se debe usar en dispositivos de envío.
Es posible que Android dé de baja la versión más antigua cuando realices la actualización. Para obtener información sobre cuándo dar de baja una versión, Android puede recopilar la cantidad de dispositivos con políticas del proveedor que ejecutan esa versión de Android y que aún reciben actualizaciones importantes de la plataforma. Si el número es inferior a un umbral determinado, esa versión deja de estar disponible.
Impacto en el rendimiento de varios atributos
Como se describe en https://github.com/SELinuxProject/cil/issues/9, una gran cantidad de atributos asignados a un tipo genera problemas de rendimiento en caso de que se pierda la caché de la política.
Se confirmó que se trataba de un problema en Android, por lo que se realizaron cambios en Android 8.0 para quitar los atributos que el compilador de políticas agregaba a la política, así como los atributos que no se usaban. Estos cambios resolvieron las regresiones de rendimiento.
Política pública del producto y del sistema_ext
A partir de Android 11, las particiones system_ext
y product
pueden exportar sus tipos públicos designados a la partición del proveedor. Al igual que la política pública de la plataforma, el proveedor usa tipos y reglas que se traducen automáticamente en los atributos con control de versión, por ejemplo, de type
a type_N
, donde N
es la versión de la plataforma para la que se compila la partición del proveedor.
Cuando las particiones system_ext
y product
se basan en la misma versión de la plataforma N
, el sistema de compilación genera archivos de asignación base para system_ext/etc/selinux/mapping/N.cil
y product/etc/selinux/mapping/N.cil
, que contienen asignaciones de identidad de type
a type_N
. El proveedor puede acceder a type
con el atributo con versión type_N
.
En caso de que solo se actualicen las particiones system_ext
y product
, por ejemplo, de N
a N+1
(o una versión posterior), mientras que el proveedor se mantiene en N
, es posible que pierda el acceso a los tipos de las particiones system_ext
y product
. Para evitar daños, las particiones system_ext
y product
deben proporcionar archivos de asignación de tipos concretos a atributos type_N
. Cada socio es responsable de mantener los archivos de asignación si va a admitir el proveedor de N
con particiones system_ext
y product
de N+1
(o versiones posteriores).
Para ello, se espera que los socios cumplan con lo siguiente:
- Copia los archivos de asignación de base generados de las particiones
N
,system_ext
yproduct
a su árbol de origen. - Modifica los archivos de asignación según sea necesario.
-
Instala los archivos de asignación en las particiones
system_ext
yproduct
deN+1
(o versiones posteriores).
Por ejemplo, supongamos que N
system_ext
tiene un tipo público llamado foo_type
. Luego, system_ext/etc/selinux/mapping/N.cil
en la partición system_ext
N
se verá de la siguiente manera:
(typeattributeset foo_type_N (foo_type)) (expandtypeattribute foo_type_N true) (typeattribute foo_type_N)
Si se agrega bar_type
a system_ext de N+1
y si bar_type
se debe asignar a foo_type
para el proveedor N
, N.cil
se puede actualizar desde
(typeattributeset foo_type_N (foo_type))
to
(typeattributeset foo_type_N (foo_type bar_type))
y, luego, se instala en la partición system_ext de N+1
.
El proveedor de N
puede seguir accediendo a foo_type
y bar_type
de system_ext.N+1
Etiquetado de contextos de SELinux
Para admitir la distinción entre la política de SE de la plataforma y la del proveedor, el sistema compila los archivos de contexto de SELinux de forma diferente para mantenerlos separados.
Contextos de archivos
En Android 8.0, se introdujeron los siguientes cambios para file_contexts
:
- Para evitar una sobrecarga de compilación adicional en el dispositivo durante el inicio,
file_contexts
deja de existir en forma binaria. En cambio, son archivos de texto de expresión regular legibles, como{property, service}_contexts
(como lo eran antes de la versión 7.0). - Los
file_contexts
se dividen en dos archivos:plat_file_contexts
file_context
de la plataforma de Android que no tiene etiquetas específicas del dispositivo, excepto para etiquetar partes de la partición/vendor
que deben etiquetarse con precisión para garantizar el funcionamiento correcto de los archivos de sepolicy.- Debe residir en la partición
system
en/system/etc/selinux/plat_file_contexts
en el dispositivo yinit
debe cargarlo al principio junto con elfile_context
del proveedor.
vendor_file_contexts
file_context
específico del dispositivo compilado combinandofile_contexts
que se encuentra en los directorios a los que apuntaBOARD_SEPOLICY_DIRS
en los archivosBoardconfig.mk
del dispositivo.- Se debe instalar en
/vendor/etc/selinux/vendor_file_contexts
en la particiónvendor
yinit
debe cargarlo al principio junto con la plataformafile_context
.
Contextos de propiedad
En Android 8.0, property_contexts
se divide en dos archivos:
plat_property_contexts
property_context
de la plataforma de Android que no tiene etiquetas específicas del dispositivo- Debe residir en la partición
system
en/system/etc/selinux/plat_property_contexts
y ser cargado porinit
al principio junto con el proveedorproperty_contexts
.
vendor_property_contexts
property_context
específico del dispositivo compilado combinandoproperty_contexts
que se encuentra en los directorios a los que apuntaBOARD_SEPOLICY_DIRS
en los archivosBoardconfig.mk
del dispositivo.- Debe residir en la partición
vendor
en/vendor/etc/selinux/vendor_property_contexts
y ser cargado porinit
al principio junto con la plataformaproperty_context
.
Contextos de servicio
En Android 8.0, service_contexts
se divide entre los siguientes
archivos:
plat_service_contexts
service_context
específico de la plataforma de Android para elservicemanager
.service_context
no tiene etiquetas específicas del dispositivo.- Debe residir en la partición
system
en/system/etc/selinux/plat_service_contexts
y ser cargado porservicemanager
al principio junto con el proveedorservice_contexts
.
vendor_service_contexts
service_context
específico del dispositivo compilado combinandoservice_contexts
que se encuentra en los directorios a los que apuntaBOARD_SEPOLICY_DIRS
en los archivosBoardconfig.mk
del dispositivo.- Debe residir en la partición
vendor
en/vendor/etc/selinux/vendor_service_contexts
y ser cargado porservicemanager
al principio junto con la plataformaservice_contexts
. - Aunque
servicemanager
busca este archivo durante el inicio, para un dispositivoTREBLE
que cumpla con todos los requisitos,vendor_service_contexts
NO DEBE existir. Esto se debe a que toda la interacción entre los procesos devendor
ysystem
DEBEN pasar porhwservicemanager
/hwbinder
.
plat_hwservice_contexts
hwservice_context
de la plataforma de Android parahwservicemanager
que no tiene etiquetas específicas del dispositivo.- Debe residir en la partición
system
en/system/etc/selinux/plat_hwservice_contexts
y ser cargado porhwservicemanager
al principio junto convendor_hwservice_contexts
.
vendor_hwservice_contexts
hwservice_context
específico del dispositivo compilado combinandohwservice_contexts
que se encuentra en los directorios a los que apuntaBOARD_SEPOLICY_DIRS
en los archivosBoardconfig.mk
del dispositivo.- Debe residir en la partición
vendor
en/vendor/etc/selinux/vendor_hwservice_contexts
y ser cargado porhwservicemanager
al principio junto conplat_service_contexts
.
vndservice_contexts
service_context
específico del dispositivo para elvndservicemanager
compilado combinandovndservice_contexts
que se encuentra en los directorios a los que apuntaBOARD_SEPOLICY_DIRS
en elBoardconfig.mk
del dispositivo.- Este archivo debe residir en la partición
vendor
en/vendor/etc/selinux/vndservice_contexts
y ser cargado porvndservicemanager
al principio.
Contextos de Seapp
En Android 8.0, seapp_contexts
se divide en dos archivos:
plat_seapp_contexts
seapp_context
de la plataforma de Android que no tiene cambios específicos del dispositivo- Debe residir en la partición
system
en/system/etc/selinux/plat_seapp_contexts.
.
vendor_seapp_contexts
- Extensión específica del dispositivo a la plataforma
seapp_context
compilada combinandoseapp_contexts
que se encuentra en los directorios a los que apuntaBOARD_SEPOLICY_DIRS
en los archivosBoardconfig.mk
del dispositivo. - Debe residir en la partición
vendor
en/vendor/etc/selinux/vendor_seapp_contexts
.
- Extensión específica del dispositivo a la plataforma
Permisos de MAC
En Android 8.0, mac_permissions.xml
se divide en dos archivos:
- Plataforma
mac_permissions.xml
mac_permissions.xml
de la plataforma de Android que no tiene cambios específicos del dispositivo- Debe residir en la partición
system
en/system/etc/selinux/.
.
- No de plataforma
mac_permissions.xml
- Extensión específica del dispositivo a la plataforma
mac_permissions.xml
compilada a partir demac_permissions.xml
que se encuentra en los directorios a los que apuntaBOARD_SEPOLICY_DIRS
en los archivosBoardconfig.mk
del dispositivo. - Debe residir en la partición
vendor
en/vendor/etc/selinux/.
.
- Extensión específica del dispositivo a la plataforma