5 votes

Comment exécuter un programme dans un contexte d'application avec Magisk ?

Disons que je suis actuellement en tant que Root dans Bash sur un terminal, en dehors de toute application comme Termux. J'utilise Magisk.

Maintenant, je veux invoquer de manière synchrone le Bash de Termux, de telle sorte qu'il se comporte de la même manière que si j'avais démarré directement l'application Termux (c'est-à-dire avec les mêmes permissions, le même contexte SELinux, le même utilisateur/groupe et tout le reste).

Comment puis-je le faire ?

5voto

Irfan Latif Points 16863

Le framework Android s'occupe de beaucoup de choses lorsqu'il s'agit de forker une application à partir de zygote . En bref, il est presque impossible d'exécuter un processus d'application à partir de la ligne de commande pour qu'il se comporte de la manière suivante "exactement de la même manière" comme si l'application était correctement lancée. Continuez à lire pour avoir une idée de la raison pour laquelle il en est ainsi.

Afin d'exécuter bash dans le contexte de l'application Termux afin qu'elle se comporte exactement de la même manière que si elle était lancée depuis l'application, elle doit au moins être exécutée :

  • Avec l'UID/GID de l'application attribué par le gestionnaire de paquets au moment de l'installation.
  • Avec groupe supplémentaire inet ( 3003 ), qui est nécessaire pour créer des sockets réseau et est attribué à toute application au moment de l'installation qui déclare android.permission.INTERNET dans son AndroidManifest.xml . Pour plus de détails, voir Comment fonctionne le mappage des permissions d'Android avec les UID/GID ? .
  • Avec groupe supplémentaire everybody ( 9997 ) qui est utilisé pour contrôler l'accès en lecture/écriture de l'application à l'adresse suivante /sdcard . Pour plus de détails, voir Qu'est-ce que l'UID "u#_everybody" ? .
  • Avec des groupes supplémentaires <uid>_cache (UID+10000) et all_<uid> (UID+40000) pour que l'application puisse accéder à son cache, au code exécutable natif, etc. Mais ces éléments ne sont pas nécessairement nécessaires puisque nous n'exécutons pas l'application elle-même.
  • En entrant dans l'espace de nom de l'application Termux ( com.termux ) qui est nécessaire pour le processus supgid 9997 pour travailler. Si l'application n'est pas en cours d'exécution (par exemple, si elle est exécutée à partir de adb shell ), supgid 1015 peut être utilisé pour obtenir un accès en écriture à /sdcard mais ce n'est pas comme ça que l'application fonctionne.
  • En abandonnant tous les Linux capacités (privilèges Root granulaires dans Efficace , Autorisé , Héritage , Délimitation y Ambiant ) ainsi que la mise en place securebits et l'attribut de contrôle du processus NO_NEW_PRIVS qui s'assure que l'application n'est pas en mesure d'élever les privilèges en faisant usage de setuid ou les capacités du fichier.
  • Avec blocage syscalls en appliquant seccomp-bpf filtre.
  • Avec le contexte SELinux de l'application, qui est déterminé à l'installation/exécution sur la base du MMAC. ( 1 , 2 ) .
  • En ajoutant le processus à des cgroups par exemple cpuset , memcg etc. comme le fait le framework d'Android.
  • Par attraper , blocage y en ignorant le même signaux comme le ferait l'application.
  • En définissant l'environnement sur lequel il s'appuie. Par exemple, le bash de Termux ne s'exécutera pas sans LD_LIBRARY_PATH dont il a besoin pour la liaison dynamique.

Il n'y a pas un seul outil en ligne de commande disponible qui puisse faire tout ce sandboxing, il ne peut être réalisé entièrement que de manière programmatique (cf. Mini-prison ), ou peuvent utiliser plusieurs outils, par ex. nsjail / firejail pour le réglage seccomp filtres, runcon pour modifier le contexte SELinux, capsh pour modifier les DAC/capacités, nsenter pour entrer dans l'espace de noms de montage, etc. setpriv de util-linux Le paquet peut faire le maximum :

~# uid=$(stat -c %u /data/data/com.termux)
~# pid=$(pidof -s com.termux)
~# label=$(cat /proc/$pid/attr/current)
~# export LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib
~# exec nsenter -t $pid -m setpriv --reuid $uid --regid $uid --groups 3003,9997 --bounding-set -all --selinux-label $label -- /system/bin/sh -c 'exec /data/data/com.termux/files/usr/bin/bash'

* nsenter y setpriv sont des applets busybox mais avec des fonctionnalités limitées. Pour aarch64 vous pouvez obtenir des binaires statiques ici : nsenter , setpriv .

Cependant, nous devons définir shell_exec (étiquette de /system/bin/sh ) comme entrypoint pour exécution par untrusted_app contexte qui ne fait pas partie du stock sepolicy (au moins sur Pie) :

~# supolicy --live 'allow untrusted_app shell_exec file entrypoint'

Exécuter /system/bin/sh avant d'exécuter /data/data/com.termux/files/usr/bin/bash est nécessaire car /data La partition est montée avec nosuid qui empêche la transition de contexte SELinux (de magisk a untrusted_app ) ( 3 ) et vous obtenez une permission refusée. Vous pouvez envisager de monter /data sans nosuid pour sauter cette étape.
Pour la même raison --no-new-privs y --selinux-label ne peuvent pas être utilisés conjointement.

Tout cela se passe dans le monde natif, rien dans la pile Java. Nous n'avons donc aucun contrôle direct sur des choses comme autorisations du manifeste qui fonctionnent entièrement dans le cadre d'Android. Cependant, l'application de la permission manifeste est également basée sur les UIDs. ( 4 ) . Par exemple, si Termux a reçu android.permission.WRITE_EXTERNAL_STORAGE le bash que nous exécutons avec l'UID de Termux sera aussi capable d'écrire sur /sdcard .


D'après votre commentaire :

Je ne comprends pas comment cela est possible. Par exemple, considérez la sortie :

u0_a129 ~$ /sbin/su --context=u:object_r:app_data_file:s0:c512,c768 u0_a129 -c /system/bin/id
uid=10129(u0_a129) gid=10129(u0_a129) groups=10129(u0_a129) context=u:r:magisk:s0
u0_a129 ~$ /system/bin/id
uid=10129(u0_a129) gid=10129(u0_a129) groups=10129(u0_a129),3003(inet),9997(everybody),20129(u0_a129_cache),50129(all_a129),99909997(u999_everybody) context=u:r:untrusted_app_27:s0:c512,c768

D'après ce que j'ai compris, c'est ainsi que fonctionne le contrôle d'accès discrétionnaire d'Unix. Tout d'abord, il faut passer --context à celui de Magisk /sbin/su ne fait aucune différence comme expliqué ici :

l'option existe toujours pour la compatibilité CLI avec les applications conçues pour SuperSU. Cependant, l'option est silencieusement ignorée car elle n'est plus pertinente.

Donc le contexte n'a pas changé, comme vous pouvez le voir, c'est toujours u:r:magisk:s0 . Deuxièmement, Magisk su n'est pas le véritable utilisateur du commutateur ( 5 ) il fournit une fonctionnalité minimale de la norme su (celui que nous avons sur Linux). Pour plus de détails, voir Comment fonctionne Magisk ?

Dans votre première commande, il a défini l'UID, le GID et les groupes supplémentaires à l'UID que vous avez fourni. Vous n'avez pas demandé su pour définir des groupes supplémentaires, ni l'un ni l'autre ne le peut.

Dans la deuxième commande, vous voyez l'UID, le GID, les groupes supplémentaires et le contexte SELinxu qui ont été définis par zygote quand il a bifurqué sur le DVM/ART de l'application ( com.termux dans le cas de Termux). Les groupes supplémentaires sont expliqués ci-dessus. 99909997 est également expliqué dans le lien donnée ci-dessus.

androidalle.com

AndroidAlle est une communauté de androiders où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X