J'ai une installation Unix qui est censée être utilisable à la fois comme chroot et comme système autonome. S'il s'exécute en tant que chroot, je ne veux exécuter aucun service (cron, inetd, etc.), car ils entreraient en conflit avec le système hôte ou seraient redondants.
Comment écrire un script shell qui se comporte différemment selon qu'il s'exécute dans un chroot ? Mon besoin immédiat est un système Linux moderne, avec /proc
monté dans le chroot et le script s'exécute en tant que root, mais des réponses plus portables sont également les bienvenues. (Voir Comment savoir si je suis en cours d'exécution dans un chroot si /proc n'est pas monté ? pour le cas de Linux sans /proc
.)
Plus généralement, des suggestions qui fonctionnent pour d'autres méthodes de confinement seraient intéressantes. La question pratique est la suivante :ce système est-il censé exécuter des services ? (La réponse étant non dans un chroot, et oui dans une machine virtuelle à part entière ; je ne connais pas les cas intermédiaires tels que les prisons ou les conteneurs.)
Réponse acceptée :
Ce que j'ai fait ici est de tester si la racine de init
processus (PID 1) est identique à la racine du processus en cours. Bien que /proc/1/root
est toujours un lien vers /
(sauf si init
lui-même est chrooté, mais ce n'est pas un cas qui m'intéresse), le suivre mène au répertoire racine "maître". Cette technique est utilisée dans quelques scripts de maintenance dans Debian, par exemple pour ignorer le démarrage d'udev après l'installation dans un chroot.
if [ "$(stat -c %d:%i /)" != "$(stat -c %d:%i /proc/1/root/.)" ]; then
echo "We are chrooted!"
else
echo "Business as usual"
fi
(Au fait, c'est encore un autre exemple de la raison pour laquelle chroot
est inutile pour la sécurité si le processus chrooté a un accès root. Les processus non root ne peuvent pas lire /proc/1/root
, mais ils peuvent suivre /proc/1234/root
s'il y a un processus en cours d'exécution avec le PID 1234 exécuté sous le même utilisateur.)
Si vous ne disposez pas des autorisations root, vous pouvez consulter /proc/1/mountinfo
et /proc/$$/mountinfo
(brièvement documenté dans filesystems/proc.txt
dans la documentation du noyau Linux). Ce fichier est lisible par tout le monde et contient de nombreuses informations sur chaque point de montage dans la vue du processus du système de fichiers. Les chemins d'accès dans ce fichier sont limités par le chroot affectant le processus de lecture, le cas échéant. Si le processus lit /proc/1/mountinfo
est chrooté dans un système de fichiers différent de la racine globale (en supposant que la racine du pid 1 est la racine globale), alors aucune entrée pour /
apparaît dans /proc/1/mountinfo
. Si le processus lit /proc/1/mountinfo
est chrooté dans un répertoire du système de fichiers racine global, puis une entrée pour /
apparaît dans /proc/1/mountinfo
, mais avec un identifiant de montage différent. Incidemment, le champ racine ($4
) indique où se trouve le chroot dans son système de fichiers maître.
[ "$(awk '$5=="/" {print $1}' </proc/1/mountinfo)" != "$(awk '$5=="/" {print $1}' </proc/$$/mountinfo)" ]
Il s'agit d'une solution purement Linux. Il peut être généralisable à d'autres variantes d'Unix avec un /proc
suffisamment similaire (Solaris a un /proc/1/root
similaire , je pense, mais pas mountinfo
).