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 :