8 votos

¿Cómo funciona el mapeo de permisos de Android con UIDs/GIDs?

Leyendo el libro: Seguridad interna de Android Estoy leyendo en Capítulo 2 - Gestión de permisos párrafo que los permisos se asignan a la aplicación en el momento de la instalación por el gestor de paquetes con un mapeo como UID de Apk <-> Permisos.

Más adelante en el libro ( Asignación de permisos - Permisos y atributos de proceso párrafo) he leído que

Si se han asignado permisos adicionales a la aplicación, se asignan a GIDs y se asignan como GIDs suplementarios al proceso.

Y, como Android.permission.INTERNET el permiso está asociado a inet GID:

cualquier proceso de una aplicación a la que se le haya concedido el permiso El permiso INTERNET se asocia con el GID suplementario correspondiente al grupo inet. al grupo inet

Pero me preguntaba si esto es siempre necesario.

Imaginando un caso en el que se instala el APK X declarando Android.permission.INTERNET permiso en AndroidManifest.xml ya que la asignación de permisos con UIDs se realiza en el momento de la instalación, PackageManager debería poder asignar el permiso directamente con el UID del APK en lugar de añadir inet GID a su paquete APK. Así que me pregunto por qué tiene que ser eso:

cualquier proceso de una aplicación a la que se le ha concedido el permiso INTERNET se asocia con el GID suplementario correspondiente al grupo inet

¿Alguien puede aclararme esto?

0 votos

Así es simplemente como funciona. Comprobar si un usuario es miembro de un grupo específico es mucho más sencillo que en cada petición tener que comprobar si un usuario está autorizado a esto y aquello.

12voto

Jack Wade Puntos 231

La gestión de permisos de Android puede dividirse principalmente en dos partes: El kernel de Linux y el framework de Android.

CONTROL DE ACCESO DISCRECIONAL:

El control de acceso discrecional (DAC) basado en usuarios, grupos y modo de acceso se remonta a los primeros días de UNIX. Cada archivo (incluidos los directorios) y proceso tiene un propietario de usuario (UID) y un propietario de grupo (GID). Así, un proceso puede leer, escribir y ejecutar un recurso dependiendo de los bits de su modo de acceso ( RWX ) para Usuario, Grupo y Otros ( UGO ). Estos atributos de permisos se guardan junto con los archivos en el sistema de archivos.
UID/GID 0 es especial para el kernel de Linux; es el súper usuario (administrador) al que nunca se le niega hacer nada. Todos los demás usuarios en el rango 1-65534 son identificaciones no privilegiadas que un SO puede utilizar de la manera que quiera para controlar el acceso.

Android reserva UIDs en el rango 1000-9999 para el uso del sistema, a diferencia de las distribuciones de Linux, donde el 1000 suele ser el primer UID asignado a los usuarios humanos. Android está diseñado para un solo usuario humano, pero cada aplicación Java, ya sea preinstalada (como aplicación de sistema o de usuario) o instalada por el usuario, es tratada como un usuario. Rango de UIDs 10000-19999 está reservado para estas aplicaciones. En el primer arranque (para las aplicaciones preinstaladas) o cuando se instala una nueva aplicación, se asigna un UID/GID único a la aplicación que es estático a menos que la aplicación se desinstale. Este mapeo de app vs. UID puede verse en el archivo /data/system/packages.list o utilizando el comando id ( 1 ) si la aplicación proporciona un shell o puede ejecutar binarios nativos.

Todos estos UID tienen nombres codificados en Android que son predefinido A diferencia de las distribuciones de Linux, en las que existen convenciones de nomenclatura para los usuarios y grupos que se pueden añadir/eliminar en /etc/passwd y /etc/group . Android sólo comparte root nombre de usuario con Linux. Sin embargo, estos nombres son sólo para la facilidad de los usuarios humanos, para el kernel sólo significan números (UID/GID).

Listas de control de acceso ( ACLs ) se puede utilizar para ampliar el DAC para obtener privilegios más granulares, pero estos se utilizan raramente en Linux y (AFAIK) no se utilizan en Android.

CAPACIDADES DE LINUX:

Las autoridades del usuario root se dividen a su vez en subgrupos denominados capacidades . En lugar de utilizar el UID 0 siempre que se vaya a realizar una tarea elevada, se puede conceder a un UID sin privilegios sólo la capacidad requerida. Las capacidades de archivo que se adjuntan a los archivos mediante atributos extendidos ( XATTR ), también se puede utilizar para elevar las capacidades del proceso siempre que sea necesario. Android hace uso de Capacidades de los archivos así como Capacidades ambientales . Ver este hilo para más detalles.

CONTROL DE ACCESO OBLIGATORIO:

El Control de Acceso Obligatorio (MAC) se introdujo posteriormente para complementar el DAC y mejorar la seguridad. Android utiliza SELinux como parte de su aplicaciones de seguridad . SELinux también hace uso de los Atributos Extendidos para etiquetar archivos con un contexto mientras que cada proceso también se ejecuta con un contexto SELinux. Entonces se define una política que incluye miles de reglas que permiten el acceso de un contexto a otro, denegado por defecto. Ver esta respuesta para más detalles sobre SELinux y un ejemplo de cómo Android hace uso de DAC, capabilities y MAC.

Haciendo uso del DAC, MAC y las capacidades del kernel de Linux, Android lanza cada aplicación en una máquina virtual de sandboxing bifurcada de zygote con su ID único y con todas las capacidades eliminadas, de modo que se vea obligado a acceder sólo a sus propios archivos en /data/data/<app_pkg_name> o en un almacenamiento externo. Ver esta respuesta para más detalles.

PERMISOS MANIFIESTOS:

Para tener un control más fino de los recursos del sistema, además de los mecanismos de control de acceso de Linux a nivel del núcleo, Android aplica su propio Permisos del Manifiesto a las aplicaciones instaladas dentro de su marco central. Estos permisos son de tres tipos : Normal, Peligroso y Firma.
Todos los permisos normales se conceden a un solicitando la aplicación sin interacción humana. Por ejemplo, un usuario no puede restringir el acceso a Internet de una aplicación si ésta solicita android.permission.INTERNET . Algunos de estos permisos se controlan utilizando herramientas de terceros.
Permisos peligrosos - como READ_CONTACTS - no se conceden a una aplicación sin la aprobación del usuario. Algunas de las Permisos de firma tratado como Permisos especiales - como REQUEST_INSTALL_PACKAGES - también se puede controlar desde Settings app > Apps & notifications > Advanced > Special app access en las nuevas versiones de Android.
Además, algunos de los permisos para los que el usuario no tiene control independiente, como GET_ACCOUNTS o las operaciones que no tienen permisos correspondientes como RUN_IN_BACKGROUND , se puede controlar desde un gestor de permisos oculto de Android: AppOps . Pero esto está pensado sólo para el uso del sistema operativo y no para los usuarios finales.

COMPROBACIÓN Y APLICACIÓN DE PERMISOS:

Las preferencias de permisos son almacenadas por Android Package Manager en diferentes archivos como /data/system/packages.list , /data/system/packages.xml , /data/system/users/0/runtime-permissions.xml en el momento de la instalación de la aplicación o en tiempo de ejecución. Estas comprobaciones de permisos son entonces se aplica en múltiples eventos como cuando se accede a los intentos, se inicia una actividad, se envía/recibe una emisión, se accede a un proveedor de contenidos, se inicia/se vincula a un servicio, etc.

Aunque todo el proceso de comprobación y aplicación de permisos sucede en zygote en el que ActivityManager y PackageManager - que forman parte de system_server - juegan un papel importante, el núcleo de la estructura no maneja todas las comprobaciones de permisos por sí mismo. Una vez más, necesita la ayuda del núcleo para que las comprobaciones de permisos sean más robustas y eficientes.
Por ejemplo LEER/ESCRIBIR_ALMACENAMIENTO_EXTERNO Los permisos se imponen a través de UIDs/GIDs mediante el montaje de diferentes vistas de Almacenamiento en un espacio de nombres de montaje para cada aplicación. Ver esta respuesta para más detalles.

PERMISO <--> MAPEO GID:

Otro caso especial en el que Android se apoya en el kernel de Linux para la comprobación de permisos es android.permission.INTERNET . Como ya se ha dicho, sólo el UID/GID 0 es especial para el núcleo estándar de Linux. Sin embargo Android aplicó un parche especial PARANOID_NETWORKING al kernel de Linux que asigna ciertas capacidades a ciertos identificaciones de grupo en el rango 3000-3999 haciéndolos especiales. Uno de ellos es INET (3003) que permite a sus miembros acceder a Internet (crear sockets PACKET) lo que no es posible sin la capacidad NET_RAW de lo contrario. Todos los permission <-> GID Las asignaciones pueden encontrarse en el archivo /sistema/etc/permisos/plataforma.xml .

Pasando a su pregunta:

ya que la asignación de permisos con UIDs se realiza en el momento de la instalación, PackageManager debería ser capaz de asignar el permiso directamente con el UID del APK en lugar de añadir el GID de inet a su paquete APK

Así que la respuesta es, PackageManager no maneja android.permission.INTERNET por su cuenta. Sólo añade la aplicación al grupo INET y guarda la configuración. Tomemos el ejemplo de Termux:

~# grep termux /data/system/packages.list
com.termux 10142 0 /data/user/0/com.termux default:targetSdkVersion=28 3003

La próxima vez que se lance la aplicación con 3003 en sus grupos suplementarios para que el kernel no restrinja el acceso a internet de la aplicación al aplicar el DAC:

~# ps -p $(pgrep com.termux) -o cmd,uid,gid,supgrp
CMD                           UID   GID SUPGRP
com.termux                  10142 10142 3003,9997,20142,50142

FUENTES:

PreguntAndroid.com

PreguntAndroid es una comunidad de usuarios de Android en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X