Woher weiß ich, dass ich in einer Chroot bin?


47

Ich besitze eine Unix-Installation, die sowohl als Chroot- als auch als Standalone-System verwendet werden kann. Wenn es als chroot ausgeführt wird, möchte ich keinen Dienst ausführen (cron, inetd usw.), da dies zu Konflikten mit dem Hostsystem führen oder redundant sein würde.

Wie schreibe ich ein Shell-Skript, das sich unterschiedlich verhält, je nachdem, ob es in einer Chroot ausgeführt wird? Mein unmittelbarer Bedarf ist ein modernes Linux-System mit eingebundener /procChroot, und das Skript wird als Root ausgeführt, aber auch portablere Antworten sind willkommen. (Siehe Wie erkenne ich, dass ich in einer Chroot-Umgebung laufe, wenn / proc nicht gemountet ist? Für den Fall von Linux ohne /proc.)

Generell wären Vorschläge interessant, die für andere Eindämmungsmethoden funktionieren. Die praktische Frage ist, ob auf diesem System Dienste ausgeführt werden sollen. (Die Antwort lautet "Nein" in einer Chroot und "Ja" in einer vollwertigen virtuellen Maschine. Ich kenne keine Zwischenfälle wie Gefängnisse oder Container.)

Antworten:


46

Ich habe hier getestet, ob die Wurzel des initProzesses (PID 1) mit der Wurzel des aktuellen Prozesses identisch ist. Obwohl /proc/1/rootes sich immer um einen Link handelt /(es sei denn, er initselbst ist chrooted, aber das interessiert mich nicht), führt das Befolgen dieses Links zum Stammverzeichnis „master“. Diese Technik wird in einigen Wartungsskripten in Debian verwendet, um beispielsweise das Starten von udev nach der Installation in einer Chroot zu überspringen.

if [ "$(stat -c %d:%i /)" != "$(stat -c %d:%i /proc/1/root/.)" ]; then
  echo "We are chrooted!"
else
  echo "Business as usual"
fi

(Übrigens ist dies ein weiteres Beispiel dafür, warum die chrootSicherheit unbrauchbar ist, wenn der Chroot-Prozess über Root-Zugriff verfügt. Nicht-Root-Prozesse können nicht lesen /proc/1/root, aber sie können folgen, /proc/1234/rootwenn ein Prozess mit der gleichen PID 1234 ausgeführt wird Benutzer.)

Wenn Sie nicht über Root-Berechtigungen verfügen, können Sie nachsehen /proc/1/mountinfound /proc/$$/mountinfo( filesystems/proc.txtin der Dokumentation zum Linux-Kernel kurz dokumentiert ). Diese Datei ist weltweit lesbar und enthält viele Informationen zu jedem Einhängepunkt in der Prozessansicht des Dateisystems. Die Pfade in dieser Datei werden durch die Chroot eingeschränkt, die sich gegebenenfalls auf den Leseprozess auswirkt. Wenn der Prozesslesevorgang /proc/1/mountinfoin ein Dateisystem verschoben wird, das sich vom globalen Stamm unterscheidet (vorausgesetzt, der Stamm von PID 1 ist der globale Stamm), wird in kein Eintrag für /angezeigt /proc/1/mountinfo. Wenn die Prozesslesung /proc/1/mountinfoin ein Verzeichnis im globalen Root-Dateisystem verschoben wird, wird ein Eintrag für in /angezeigt /proc/1/mountinfo, jedoch mit einer anderen Mount-ID. Übrigens ist das Wurzelfeld ($4) gibt an, wo sich die Chroot in ihrem Master-Dateisystem befindet.

[ "$(awk '$5=="/" {print $1}' </proc/1/mountinfo)" != "$(awk '$5=="/" {print $1}' </proc/$$/mountinfo)" ]

Dies ist eine reine Linux-Lösung. Es ist möglicherweise verallgemeinerbar auf andere Unix-Varianten mit einer hinreichend ähnlichen /proc(Solaris hat eine ähnliche /proc/1/root, denke ich, aber nicht mountinfo).


1
Dies wird in OpenBSD nicht funktionieren, da es zufällige PIDs hat ; Der Root-Prozess ist im Grunde nie PID 1. Jetzt wissen Sie warum!
Adam Katz

@AdamKatz "... mit ein paar offensichtlichen Ausnahmen, zB init (8)." Also was ist es?
Muru

@muru: aw, shucks. Du hast mich erschossen. Ich bin mir nicht sicher, warum ich init(8)unbedingt den ersten Slot haben müsste, es sei denn, es gibt eine Art hartcodierte Art, die dies erfordert (bei der ich mir immer noch nicht sicher bin, warum ). Natürlich haben die BSDs viel weiter fortgeschrittene Gefängnisse als nur Chroot, daher bin ich mir nicht mal sicher, wie problematisch dies ist.
Adam Katz

4
@AdamKatz Es ist das Gegenteil: PID 1 hat eine besondere Rolle (es muss Zombies ernten, und es ist immun gegen SIGKILL). Das init-Programm ist eine Implementierung dieser Rolle. Der Grund, warum meine Antwort in OpenBSD nicht funktioniert, hat nichts damit zu tun: OpenBSD hat nichts Ähnliches wie Solaris / Linux /proc. Meine Antwort sollte sowieso nichts anderes als Linux ansprechen.
Gilles 'SO- hör auf böse zu sein'

@ Gilles Ich dachte, OpenBSD hätte dies auf die eine oder andere Weise besiegt. Trotzdem wundert es mich, dass all diese speziellen Rollenelemente nicht (ohne Konsequenzen) auf eine beliebige PID angewendet werden können, was ich in meinem kursiv geschriebenen "Warum" vorhin gemeint habe.
Adam Katz

22

Wie in erwähnt tragbare Art und Weise zu Inode - Nummer zu finden und Erkennen eines chroot - Gefängnis von innen , können Sie überprüfen , ob die Inode - Nummer der /ist 2:

$ ls -di /
2 /

Eine Inode-Nummer, die sich von 2 unterscheidet, zeigt an, dass das scheinbare Stammverzeichnis nicht das tatsächliche Stammverzeichnis eines Dateisystems ist. Dies erkennt keine Chroots, die auf einem Mount-Punkt oder auf Betriebssystemen mit zufälligen Root-Inode-Nummern gerootet sind .


Auf welchen Dateisystemen funktioniert diese Heuristik?
Gilles 'SO- hör auf böse zu sein'

Getestet auf ext3 und hfs.
l0b0

Also habe ich rumgespielt und ich glaube, ich habe eine zuverlässigere Methode gefunden, für die keine Root-Berechtigungen erforderlich sind (nur Linux). Ich bin immer noch offen für Gegenbeispiele oder tragbarere Methoden.
Gilles 'SO- hör auf böse zu sein'

6
Dies gilt für ext [234], jedoch nicht für alle Dateisysteme. Es wird auch nur geprüft, ob Ihr Root-Verzeichnis das Root-Verzeichnis des Dateisystems ist, das möglicherweise nicht als echtes Root-Verzeichnis angehängt ist. Mit anderen Worten, wenn Sie eine andere Partition in / jail und mounten chroot /jail, sieht dies für diesen Test wie die eigentliche Wurzel aus.
Psusi

1
@AdamKatz Anscheinend nicht. Getestet in openbsd 6.0-stable ist die Inode-Nummer immer noch 2 für den eigentlichen Root-Pfad, während es sich um eine Zufallszahl für die Chroot handelt.
Dmitri DB

5

Wenn Sie sich auf einem Debian-basierten System befinden, versuchen Sie es, obwohl dies eindeutig nicht so portabel ist wie viele andere hier aufgelistete Optionen ischroot.

Siehe: https://manpages.debian.org/jessie/debianutils/ischroot.1.de.html

So rufen Sie den Status mit ischroot direkt in der Konsole ab:

ischroot;echo $?

Ausgangscodes:

0 if currently running in a chroot
1 if currently not running in a chroot
2 if the detection is not possible (On GNU/Linux this happens if the script is not run as root).
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.