9 votes

Comment lancer un exécutable au démarrage et le maintenir en fonctionnement ?

J'ai un exécutable construit à partir d'un ndk-build programme. Je veux l'exécuter sur un appareil Android enraciné. Quelle est la probabilité qu'Android tue mon exécutable ?

使用方法 adb shell Je suis capable d'exécuter mon exécutable en utilisant les commandes suivantes :

adb push executable /sdcard
adb shell
device:/ $ su
device:/ # cd /system
device:/system # mount -o rw,remount /system
device:/system # mv /sdcard/executable .
device:/system # ./executable

Mon exigence est de lancer cet exécutable au démarrage du périphérique.

J'ai essayé ce qui suit :

  1. Écrire à ./executable en init.rc .
    • Au redémarrage init.rc réinitialisé à son contenu original. J'ai compris que Magisk faisait ça.
  2. Ecrire les commandes dans /system/etc/init/bootstat.rc
    • ./executable
    • service custom /system/executable
    • on boot ./system/dhandler/diag_revealer

Rien de ce qui précède ne fonctionne.

16voto

Irfan Latif Points 16863

Quelle est la probabilité qu'Android tue mon exécutable ?

Les processus natifs privilégiés ne sont généralement pas tués par Android, sauf s'ils ne peuvent pas gérer une erreur survenue à l'intérieur, comme une ressource système non disponible ou une permission refusée à cause de SELinux, etc. Pour libérer de la mémoire, Android ne tue que les processus dans son cadre, c'est-à-dire ceux qui tournent sous zygote . Pour gérer les ressources des processus natifs, Android utilise cgroups .

Les processus sont tués lorsqu'ils reçoivent des SIGNAUX du noyau ou d'autres programmes en espace utilisateur (par exemple avec kill commande) ( 1 , 2 ) . Le noyau est le système d'exploitation réel, non visible pour nous, mais qui gère tout ce que nous faisons avec le périphérique. Un développeur peut programmer son code pour qu'il réagisse à un signal spécifique s'il est reçu, ou pour qu'il l'ignore complètement. ( 3 ) . Sauf SIGKILL . Ce qui ne peut pas être géré par le programme, sans avertissement du noyau, sans période de grâce pour sortir en toute sécurité, juste en étant terminé immédiatement. Mais le noyau ne se préoccupera pas de votre présence à moins qu'il ne soit à court de ressources matérielles ou que vous commenciez à mal vous comporter. C'est pourquoi la programmation est importante.

Les programmes peuvent s'envoyer des signaux (y compris KILL), qui sont transmis par le noyau et régis par l'UID. ( 4 ) . Cependant, init le tout premier processus en espace utilisateur démarré par le noyau est le cher, le noyau n'avance jamais dangereux signaux pour init . Et si cela se produit pour une raison quelconque, le noyau panique et redémarre. ( 5 ) .

En résumant les lignes ci-dessus, il est possible d'éviter d'être tué (AMAP) de manière programmatique ou en utilisant certains éléments de l'AMAP. astuces de script comme @ alecxs a mentionné. Mais si vous voulez vous assurer que votre processus doit redémarrer s'il est tué, définissez un fichier Android init service.

Au redémarrage init.rc réinitialisé à son contenu original. J'ai compris que Magisk faisait ça.

Non, Magisk n'a pas fait ça. L'Android rootfs est un système de fichiers temporaire (et non un système persistant comme dans le cas de /system o /data ) qui est effacée à chaque redémarrage. Contenu du répertoire racine ( / ) sont extraites d'une autre partition nommée boot qui contient kernel y ramdisk (bien que les choses aient changé avec système-as-Root ). Vous ne pouvez donc pas modifier init.rc de façon permanente à moins que vous n'extrayez, modifiez, ré-empaqueter et re-flasher boot.img .

Mais pour définir un nouveau service init, il faut modifier init.rc n'est pas nécessaire. Android analyse tous les .rc des fichiers de /etc/init situés sous /system y /vendor ( 6 ) . Vous pouvez donc créer votre propre .rc fichier.


NOTE : Afin d'obtenir de vrais privilèges Root et de traiter avec SELinux, toutes les options données ci-dessous dépendent de Magisk. Voir cette réponse pour les détails.

SCRIPT INIT.D

Vous pouvez utiliser les méthodes traditionnelles init.d -comme la fonction de Magisk pour démarrer un processus au démarrage. Créer un script /data/adb/service.d/custom.sh :

#!/system/bin/sh

# write log file if executable throws something at stdout/sterr
exec >>/data/media/0/executable.log 2>&1

# run script in background to avoid blocking boot chain
[ -n "$BG" ] || { BG=Y "$0" & exit; }

# try to ignore signals as much as possible
for i in $(seq 64); do trap '' "$i"; done

# execute script whenever exits e.g. when executable gets killed
trap "sleep 5; exec $0" EXIT

# avoid multiple instances e.g. if script killed but executable is running
pkill -9 -x /system/bin/executable

# execute the binary, should run in foreground, otherwise get in loop
echo "$(date): Starting program..."
/system/bin/executable

# program is killed, won't reach here if script is killed
echo "$(date): Re-executing script..."

* EXIT est la coquille pseudo-signal .
* Android's /system/bin/pkill (de toybox ) est bogué, mieux vaut utiliser busybox applet.

Placez l'exécutable sous /system/bin et définir les permissions :

~# chown 0.0 /system/bin/executable /data/adb/service.d/custom.sh
~# chmod 0755 /system/bin/executable /data/adb/service.d/custom.sh

Vous pouvez également placer le script sous /data/adb/post-fs-data.d/ mais c'est exécuté un peu plus tôt. Assurez-vous que les chemins du système de fichiers (et les autres ressources nécessaires, le cas échéant) sont disponibles à ce stade.

EXÉCUTER LE PROGRAMME DEPUIS INIT

Une autre façon est d'exécuter directement le binaire depuis init. Créer custom.rc fichier :

#/etc/init/custom.rc

# execute the binary when boot is completed
on property:sys.boot_completed=1
    exec_background u:r:magisk:s0 -- /system/bin/executable

Définir les autorisations :

~# chown 0.0 /etc/init/custom.rc
~# chmod 0644 /etc/init/custom.rc
~# chcon u:object_r:system_file:s0 /etc/init/custom.rc

Et c'est tout ! Redémarrez l'appareil pour que les changements prennent effet.

Cependant, c'est une exécution unique, qui ne sera pas relancée. De plus, certaines fonctions de script shell ne sont pas disponibles dans le module .rc fichiers. Par exemple, vous ne pouvez pas rediriger stdout/stderr vers un fichier, cela doit être géré par le programme exécutable lui-même. Nous pouvons donc essayer d'utiliser les deux : le script shell et le programme exécutable. .rc fichier :

INIT SERVICE

Au lieu d'exécuter directement les binaires de .rc exécutez un script shell. Créer un script /system/bin/custom.sh :

#!/system/bin/sh

# write log file if executable throws something at stdout/sterr
exec >>/data/media/0/executable.log 2>&1

# execute the binary, should run in foreground, otherwise get in loop
echo "$(date): Starting program..."
exec /system/bin/executable

Créer init service :

#/etc/init/custom.rc

# define service, use executable here if script not needed
service custom /system/bin/custom.sh

    # don't start unless explicitly asked to
    disabled

    # only execute once, don't restart if exited
    # don't add if you want to restart service when killed
    #oneshot

    # run with unrestricted SELinux context to avoid avc denials
    # it's required if SELinux is enforcing and service needs access
    # to some system resources not allowed by default sepolicy
    seclabel u:r:magisk:s0

# start the service when boot is completed
on property:sys.boot_completed=1
    start custom

Définir les autorisations sur executable , custom.sh y custom.rc comme indiqué ci-dessus et redémarrer.

Autres paramètres ( 7 ) comme user , group , capabilities sont nécessaires si vous voulez exécuter le service en tant qu'utilisateur non privilégié. Attribution de les privilèges les moins requis est l'approche recommandée du point de vue de la sécurité. Voir cette réponse pour plus de détails sur les capacités et SELinux.

init continuera à redémarrer le service toutes les 5 secondes (par défaut) s'il est tué. Vous pouvez arrêter le service avec setprop ctl.stop custom . Remplacer stop con start pour recommencer.
Pour voir ce qui se passe avec le service : dmesg | grep init: | tail .

RELATED :

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