Ich weiß, dass Linux-Namespaces unter vielen anderen Dingen genutzt werden können, um das Einschränken und Jailen von untergeordneten Prozessen sicher zu handhaben, ohne dass die Möglichkeit besteht, dass sie zombifiziert und auf init
abgelegt werden . Aber ich bin unscharf in Bezug auf Implementierungsdetails. Wie kann ich die von util-linux
bereitgestellten Tools verwenden wie mount
und nsenter
um zu beobachten, zu überwachen und sicherzustellen, dass alle gestarteten Prozesse die direkten Namespace-Nachkommen eines anderen Prozesses sind?
Akzeptierte Antwort:
Erstellen Sie einen PID-Namensraum
Der richtige Befehl, den Sie hier verwenden sollten, ist unshare
. Beachten Sie, dass die dafür notwendigen Optionen erst ab util-linux 2.23
verfügbar sind . Die Idee ist, einen neuen PID-Namensraum für das Programm zu erstellen, das Sie ausführen, sodass alle seine Kinder ebenfalls in diesem Namensraum erstellt werden. Sie können einen Befehl in einem neuen PID-Namensraum ausführen, indem Sie einfach Folgendes tun:
sudo unshare -fp some_command
Um eine Shell auszuführen, lassen Sie einfach den Befehl weg. Dadurch wird ein Prozess erstellt, der zusammen mit seinen untergeordneten Prozessen wie üblich eine PID innerhalb des übergeordneten (System-) Namensraums hat. Innerhalb des neuen Namensraums wird es jedoch eine PID von 1
haben zusammen mit einigen der besonderen Eigenschaften von init
Prozess. Das vielleicht relevanteste Merkmal aus Sicht der Überwachung ist, dass, wenn einer seiner Nachkommen verwaist ist, sie diesem Prozess wieder übergeordnet werden und nicht dem echten init
verarbeiten.
Dies kann für die meisten Überwachungsfälle ausreichen. Wie bereits erwähnt, haben alle Prozesse innerhalb des Namensraums PIDs innerhalb des übergeordneten Namensraums, sodass reguläre Befehle verwendet werden können, um ihre Aktivität zu überwachen. Uns wird auch versichert, dass, wenn ein Prozess im Namensraum verwaist, er nicht aus den Prozessbaumzweigen unterhalb der PID des Programms der obersten Ebene herausfallen wird, was bedeutet, dass er immer noch leicht verfolgt werden kann.
Mit einem Mount-Namespace kombinieren
Was wir jedoch nicht tun können, ist, den Prozess in Bezug auf die PID zu überwachen, die er denkt das hat. Dazu und insbesondere um den ps
verwenden zu können Befehl innerhalb des neuen Namensraums, müssen Sie ein separates procfs
einhängen Dateisystem für den Namespace. Dies wiederum führt zu einem weiteren Problem, da der einzige Standort ps
akzeptiert für procfs
ist /proc
. Eine Lösung wäre, eine chroot
zu erstellen Jail und mounten Sie die neuen procfs
dort. Dies ist jedoch ein umständlicher Ansatz, da wir zumindest alle Binärdateien, die wir verwenden möchten, zusammen mit allen Bibliotheken, von denen sie abhängen, in das neue Stammverzeichnis kopieren (oder zumindest fest verlinken) müssten.
Die Lösung besteht darin, auch einen neuen mount namespace zu verwenden . Darin können wir die neuen procfs
einhängen auf eine Weise, die den wahren Stamm /proc
verwendet Verzeichnis, kann innerhalb des PID-Namensraums verwendet werden und stört nichts anderes. Um diesen Vorgang sehr einfach zu gestalten, wird die unshare
Befehl gibt den --mount-proc
Möglichkeit:
sudo unshare -fp --mount-proc some_command
Jetzt läuft ps
innerhalb der kombinierten Namensräume zeigt nur die Prozesse mit dem PID-Namensraum und zeigt den Prozess der obersten Ebene mit einer PID von 1
.
Was ist mit nsenter
?
Wie der Name schon sagt, nsenter
kann verwendet werden, um einen Namensraum einzutragen, der bereits mit unshare
erstellt wurde . Dies ist nützlich, wenn wir Informationen abrufen möchten, die nur innerhalb des Namensraums von einem ansonsten nicht verwandten Skript verfügbar sind. Der einfachste Weg besteht darin, auf die PID eines beliebigen Programms zuzugreifen, das innerhalb des Namensraums ausgeführt wird. Zur Verdeutlichung muss dies die PID des Zielprogramms innerhalb des Namensraums sein, aus dem nsenter
stammt ausgeführt wird (da Namensräume verschachtelt werden können, kann ein einzelner Prozess viele PIDs haben). Um eine Shell im Ziel-PID/Mount-Namensraum auszuführen, tun Sie einfach:
sudo nsenter -t $PID -m -p
Wenn dieser Namensraum wie oben eingerichtet ist, wird ps
listet jetzt nur Prozesse innerhalb dieses Namensraums auf.