user_namespaces(7) Miscellaneous Information Manual user_namespaces(7) BEZEICHNUNG user_namespaces - Uberblick uber Benutzernamensraume in Linux BESCHREIBUNG Fur einen Uberblick uber Namensraume, siehe namespaces(7). Benutzernamensraume isolieren sicherheitsrelevante Kennzeichner und Attribute, insbesondere Benutzer- und Gruppenkennungen (siehe credentials(7)), das Wurzelverzeichnis, Schlussel (siehe keyrings(7)) und Capabilitys (siehe capabilities(7)). Die Benutzer- und Gruppenkennung eines Prozesses kann innerhalb und ausserhalb eines Benutzernamensraums verschieden sein. Insbesondere kann ein Prozess eine normale, nicht privilegierte Benutzerkennung ausserhalb eines Benutzernamensraums haben, wahrend er gleichzeitig eine Benutzerkennung 0 innerhalb des Namensraums hat; mit anderen Worten, der Prozess hat volle Privilegien fur Aktionen innerhalb des Benutzernamensraums, ist aber fur Aktionen ausserhalb des Namensraums nicht privilegiert. Verschachtelte Namensraume, Namensraum-Mitgliedschaft Benutzernamensraume konnen verschachtelt werden, das bedeutet, dass jeder Benutzernamensraum-ausser dem anfanglichen (>>Wurzel-<<)Namensraum-uber einen Vorgangernamensraum verfugt und keinen oder mehrere Nachfolgernamensraume haben kann. Der Vorgangernamensraum ist der Benutzernamensraum des Prozesses, der den Benutzernamensraum mittels eines Aufrufs von unshare(2) oder clone(2) mit dem Schalter CLONE_NEWUSER erstellte. (Seit Linux 3.11) erzwingt der Kernel eine Begrenzung von 32 verschachtelten Stufen an Benutzernamensraumen. Aufrufe an unshare(2) oder clone(2), die zum Uberschreiten dieser Begrenzung fuhren wurden, schlagen mit dem Fehler EUSERS fehl. Jeder Prozess ist Mitglied in genau einem Benutzernamensraum. Ein mit fork(2) oder clone(2) ohne den Schalter CLONE_NEWUSER erstellter Prozess ist ein Mitglied im gleichen Benutzernamensraum wie sein Elternprozess. Ein Prozess mit nur einem Thread kann einem anderen Benutzernamensraum mit setns(2) beitreten, falls er uber CAP_SYS_ADMIN in diesem Namensraum verfugt; wenn er dies durchfuhrt, erlangt er den vollstandigen Satz an Capabilitys in diesem Namensraum. Ein Aufruf von clone(2) oder unshare(2) mit dem Schalter CLONE_NEWUSER fuhrt dazu, dass der Kindprozess (fur clone(2)) oder der Aufrufende (fur unshare(2)) ein Mitglied des neuen, durch den Aufruf erstellten Benutzernamensraums wird. Die Aktion NS_GET_PARENT ioctl(2) kann zum Erkennen der Vorganger-/Nachfolger-Beziehung von Benutzernamensraumen verwandt werden; siehe ioctl_nfs(2). Ein Task, der eine seiner effektiven Kennungen andert, bekommt sein >>dumpable<< auf den in /proc/sys/fs/suid_dumpable angegebenen Wert zuruckgesetzt. Dies kann die Eigentumerschaft von Proc-Dateien von Kindprozessen betreffen und kann daher dazu fuhren, dass dem Elternprozess Berechtigungen fehlen, um in Mapping-Dateien des Kindprozesses, die in neuen Benutzernamensraumen ausgefuhrt werden, zu schreiben. Das Problem kann korrigiert werden, indem in diesen Fallen der Elternprozess mittels PR_SET_DUMPABLE in einem Aufruf von prctl(2) vor der Erstellung des Kindprozesses in einem neuen Benutzernamensraum >>dumpable<< gemacht wird. Siehe prctl(2) und proc(5) zu Details wie die Eigentumerschaft betroffen ist. Capabilitys Der durch clone(2) mit dem Schalter CLONE_NEWUSER erstellte Kindprozess beginnt mit einem vollstandigen Satz an Capabilitys in dem neuen Benutzernamensraum. Entsprechend erlangt ein Prozess, der einen neuen Benutzernamensraum mittels unshare(2) erstellt oder ihm mittels setns(2) beitritt, einen vollstandigen Satz an Capabilitys in diesem Namensraum. Anderserseits hat dieser Prozess keine Capabilitys in dem Vorganger- (im Falle von clone(2)) oder vorhergehenden (im Falle von unshare(2) und setns(2)) Benutzernamensraum, selbst falls der neue Namensraum vom Benutzer root erstellt wird oder dieser ihm beitritt (d.h. einem Prozess mit der Benutzerkennung 0 im Wurzel-Namensraum). Beachten Sie, dass ein Aufruf von execve(2) dazu fuhrt, dass die Capabilitys eines Prozesses auf die normale Art und Weise erneut berechnet werden (siehe capabilities(7)). Folglich wird der Prozess alle Capabilitys verlieren, ausser er hat eine Benutzerkennung von 0 innerhalb des Namensraums oder die ausfuhrbare Datei hat eine vererbbare Capability-Maske, die nicht leer ist. Siehe die nachfolgende Diskussion von Benutzer- und Gruppenkennungabbildung. Ein Aufruf von clone(2) oder unshare(2) mit dem Schalter CLONE_NEWUSER oder ein Aufruf von setns(2), der den Aufrufenden in einen anderen Benutzernamensraum verschiebt, setzt die Schalter >>securebits<< (siehe capabilities(7)) im Kind (fur clone(2)) oder dem Aufrufenden (fur unshare(2) oder setns(2)) auf ihre Vorgabewerte (alle Schalter deaktiviert). Beachten Sie, dass der Aufrufende nach einem Aufruf von setns(2) keine Capabilitys in seinem ursprunglichen Benutzernamensraum mehr hat und es daher fur einen Prozess nicht moglich ist, seine Schalter >>securebits<< zuruckzusetzen und gleichzeitig seine Mitgliedschaft im Benutzernamensraum zu erhalten, indem ein Paar von setns(2)-Aufrufen verwandt wird, um sich in einen anderen Benutzernamensraum zu verschieben und dann zu seinem ursprunglichen Namensraum zuruckzukehren. Die Regeln zur Bestimmung, ob ein Prozess eine Capability in einem bestimmten Benutzernamensraum hat, sind wie folgt: o Ein Prozess hat eine Capability innerhalb eines Benutzernamensraums, falls er ein Mitglied dieses Namensraums ist und er die Capability in seiner effektiven Capability-Menge hat. Ein Prozess kann Capabilitys in seiner effektiven Capability-Menge auf verschiedene Arten erlangen. Beispielsweise konnte er ein set-user-ID-Programm oder eine ausfuhrbare Datei mit zugeordneten Datei-Capabilitys ausfuhren. Zusatzlich konnte ein Prozess Capabilitys mittels der bereits beschriebenen Auswirkungen von clone(2), unshare(2) oder setns(2) erlangen. o Falls ein Prozess eine Capability in einem Benutzernamensraum hat, dann hat es diese Capability in allen nachfolgenden (und weiter entfernten Nachfolge-) Namensraumen ebenfalls. o Wenn ein Benutzernamensraum erstellt wird, zeichnet der Kernel die effektive Benutzerkennung des erstellenden Prozesses als >>Eigentumer<< des Namensraums auf. Ein Prozess, der sich im Vorganger des Benutzernamensraums befindet und dessen effektive Benutzerkennung auf die des Eigentumers des Namensraums passt, hat alle Capabilitys in diesem Namensraum. Dank der vorherigen Regel bedeutet dies, dass der Prozess auch uber alle Capabilitys in allen weiteren entfernten nachfolgenden Benutzerraumen verfugt. Die Aktion NS_GET_OWNER_UID ioctl(2) kann zum Ermitteln der Benutzerkennung des Eigentumers des Namensraums verwandt werden; siehe ioctl_nfs(2). Auswirkungen von Capabilitys innerhalb eines Benutzernamensraums Hat ein Prozess eine Capability innerhalb eines Benutzernamensraums, dann darf er Aktionen nur auf Ressourcen anwenden (die Privilegien benotigen), die durch diesen Namensraum reguliert werden. Mit anderen Worten erlaubt eine Capability in einem Benutzernamensraum einem Prozess, privilegierte Aktionen auf Ressourcen durchzufuhren, die durch (Nichtbenutzer-)Namensraume gelenkt werden, die den Benutzernamensraumen gehoren bzw. diesen zugeordnet sind (siehe den nachsten Unterabschnitt). Auf der anderen Seite gibt es viele privilegierte Aktionen, die Ressourcen betreffen, die keinem Namensraumtyp zugeordnet sind, beispielsweise dem Andern der Systemzeit (z.B. Kalender) (wird durch CAP_SYS_TIME reguliert), dem Laden eines Kernelmoduls (wird durch CAP_SYS_MODULE reguliert) und dem Erstellen eines Gerates (wird durch CAP_MKNOD reguliert). Nur Prozesse, die uber Privilegien in dem ursprunglichen Benutzernamensraum verfugen, konnen solche Aktionen durchfuhren. Wenn ein Prozess CAP_SYS_ADMIN innerhalb eines Namensraums halt, der den Einhangenamensraum des Prozesses besitzt, dann kann er Bind-Einhangungen erstellen und die folgenden Arten an Dateisystemen einhangen: o /proc (seit Linux 3.8) o /sys (seit Linux 3.8) o devpts (seit Linux 3.9) o tmpfs(5) (seit Linux 3.9) o ramfs (seit Linux 3.9) o mqueue (seit Linux 3.9) o bpf (seit Linux 4.4) o overlayfs (seit Linux 5.11) Wenn ein Prozess CAP_SYS_ADMIN innerhalb eines Namensraums halt, der den Cgroup-Namensraum des Prozesses besitzt, dann kann er (seit Linux 4.6) das Cgroup-Version-2-Dateisystem und die benannten Cgroup-Version-1-Hierarchien (d.h. Cgroup-Dateisysteme, die mit der Option >>none,name=<< eingehangt sind) einhangen. Wenn ein Prozess CAP_SYS_ADMIN innerhalb eines Namensraums halt, der den PID-Namensraum des Prozesses besitzt, dann kann er (seit Linux 3.8) /proc-Dateisysteme einhangen. Beachten Sie, dass das Einhangen blockbasierter Dateisysteme nur von Prozessen erfolgen kann, die CAP_SYS_ADMIN in dem anfanglichen Benutzernamensraum enthalten. Wechselwirkung von Benutzernamensraumen und anderen Arten von Namensraumen Seit Linux 3.8 konnen nicht privilegierte Prozesse Benutzernamensraume erstellen und andere Arten von Namensraumen konnen nur mit der Capability CAP_SYS_ADMIN im Benutzernamensraum des Aufrufenden erstellt werden. Wenn ein Nichtbenutzer-Namensraum erstellt wird, gehort er dem Benutzernamensraum, in dem der erstellende Prozess zum Erstellungszeitraum des Namensraums Mitglied war. Privilegierte Aktionen auf Ressourcen, die von einem Nichtbenutzer-Namensraum reguliert werden, benotigen, dass der Prozess uber die notwendigen Capabilitys in dem Benutzernamensraum verfugt, der den Nichtbenutzer-Namensraum besitzt. Falls CLONE_NEWUSER zusammen mit anderen Schaltern CLONE_NEW* in einem einzelnen Aufruf von clone(2) oder unshare(2) angegeben wird, wird garantiert, dass der Namensraum zuerst erstellt wird, und damit dem Kindprozess (clone(2)) oder dem aufrufenden Prozess (unshare(2)) Privilegien uber den durch den Aufruf erstellten Namensraum gegeben wird. Daher ist es fur einen nicht privilegierten Aufrufenden moglich, diese Schalterkombination festzulegen. Wenn ein neuer Namensraum (der kein Benutzernamensraum ist) mittels clone(2) oder unshare(2) erstellt wird, zeichnet der Kernel den Benutzernamensraum des erstellenden Prozesses als Eigentumer des neuen Namensraums auf. (Diese Zuordnung kann nicht geandert werden). Wenn nachfolgend ein Prozess in dem neuen Namensraum eine privilegierte Aktion durchfuhrt, die auf globalen Ressourcen agiert, die durch den Namensraum isoliert werden, dann erfolgen die Berechtigungsprufungen gemass der Capabilitys des Prozesses in dem Benutzernamensraum, den der Kernel dem neuen Namensraum zuordnet. Wird beispielsweise angenommen, dass ein Prozess versucht, den Rechnernamen, eine durch UTS-Namensraume regulierte Ressource, zu andern (sethostname(2)), dann wird der Kernel bestimmen, welchem Benutzernamensraum der UTS-Namensraum des Prozesses gehort und prufen, ob der Prozess uber die benotigte Capability (CAP_SYS_ADMIN) in diesem Benutzernamensraum verfugt. Die Aktion NS_GET_USERNS ioctl(2) kann zum Erkennen des Benutzernamensraums verwandt werden, dem der Nichtbenutzer-Namensraum gehort; siehe ioctl_nfs(2). Benutzer- und Gruppenkennungabbildungen: uid_map und gid_map Wenn ein Benutzernamensraum erstellt wird, beginnt er mit einer Abbildung der Benutzerkennungen (Gruppenkennungen) auf die des Vorgangernamensraumes. Die Dateien /proc/PID/uid_map und /proc/PID/gid_map (verfugbar seit Linux 3.5) legen diese Abbildungen fur die Benutzer- und Gruppenkennungen innerhalb des Benutzernamensraumes fur den Prozess PID offen. Diese Dateien konnen ausgelesen werden, um die Abbildungen innerhalb eines Benutzernamensraums zu betrachten und (einmal) beschrieben zu werden, um diese Abbildungen zu definieren. Die Beschreibung in den folgenden Absatzen erklart die Details fur uid_map; gid_map ist vollstandig identisch, sofern jedes Vorkommen von >>Benutzerkennung<< durch >>Gruppenkennung<< ersetzt wird. Die Datei uid_map legt die Abbildung der Benutzerkennung von dem Benutzernamensraum des Prozesses PID in den Benutzernamensraum des Prozesses offen, der uid_map offnete (siehe aber auch die nachfolgende Qualifizierung dieses Punktes). Mit anderen Worten, Prozesse, die sich in verschiedenen Benutzernamensraumen befinden, werden moglicherweise andere Werte sehen, wenn sie aus einer bestimmten Datei uid_map lesen, abhangig von der Benutzerkennungsabbildung fur den Benutzernamensraum des lesenden Prozesses. Jede Zeile der Datei uid_map legt eine 1-zu-1-Abbildung des Bereichs fortlaufender Benutzerkennungen zwischen zwei Benutzernamensraumen fest. (Wenn ein Benutzernamensraum erstmalig erstellt wird, ist diese Datei leer.) Die Festlegung in jeder Zeile hat die Form von drei durch Leerraum getrennten Zahlen. Die ersten zwei Zahlen geben die am Anfang befindliche Benutzerkennung in jedem der zwei Benutzernamensraume an. Die dritte Zahl gibt die Lange des abgebildeten Bereichs an. Im Detail werden die Felder wie folgt interpretiert: (1) Der Anfang des Bereichs von Benutzerkennungen in dem Benutzernamensraum des Prozesses PID. (2) Der Anfang des Bereichs von Benutzerkennungen, auf die die Benutzerkennungen aus Feld eins abgebildet werden. Wie Feld zwei interpretiert wird, hangt davon ab, ob der Prozess, der uid_map offnete und der Prozess PID sich in dem gleichen Benutzernamensraum befinden, wie folgt: (a) Falls sich die zwei Prozesse in verschiedenen Benutzernamensraumen befinden: Feld zwei ist der Anfang des Bereichs von Benutzerkennungen in dem Benutzernamensraum des Prozesses, der uid_map offnete. (b) Falls die zwei Prozesse im gleichen Benutzernamensraum sind: Feld zwei ist der Anfang des Bereichs von Benutzerkennungen in dem Vorgangerbenutzernamensraum des Prozesses PID. Dieser Fall ermoglicht es dem Offnenden von uid_map (der typische Fall hier ist das Offnen von /proc/self/uid_map) die Abbildung der Benutzerkennungen in den Benutzernamensraum des Prozesses, der diesen Benutzernamensraum erstellte, zu sehen. (3) Die Lange des Bereichs von Benutzerkennungen, die zwischen den zwei Benutzernamensraumen abgebildet wird. Systemaufrufe, die Benutzerkennungen (Gruppenkennungen) zuruckliefern-beispielsweise getuid(2), getgid(2) und die Berechtigungsdatenfelder in der durch stat(2) zuruckgelieferten Struktur-liefern die Benutzerkennung (Gruppenkennung) abgebildet auf den Benutzernamensraum des Aufrufenden zuruck. Wenn ein Prozess auf eine Datei zugreift, werden seine Benutzer- und Gruppenkennungen zum Zwecke der Zugriffsprufung und der Zuweisungen von Kennungen beim Erstellen von Dateien auf die des anfanglichen Benutzernamensraumens abgebildet. Wenn ein Prozess die Dateibenutzer- und -gruppenkennungen uber stat(2) ermittelt, werden die Kennungen in die andere Richtung abgebildet, um Werte relativ zu den Prozessbenutzer- und -gruppenkennungsabildungen zu erstellen. Der anfangliche Benutzernamensraum hat keinen Vorgangernamensraum. Aus Konsistenzgrunden stellt der Kernel Pseudo-Benutzer- und -Gruppenkennungsabbildungsdateien fur diesen Namensraum bereit. Wird vom anfanglichen Namensraum aus auf die Datei uid_map (gid_map ist identisch) geschaut, ergibt sich: $ cat /proc/$$/uid_map 0 0 4294967295 Diese Abbildung teilt uns mit, dass der Bereich bei der Benutzerkennung 0 in diesem Namensraum auf den Bereich beginnend bei 0 in dem (nicht existierenden) Vorgangernamensraum abgebildet ist und die Lange des Bereichs die grosste vorzeichenlose 32-bit-Ganzzahl ist. Dies lasst 4294967295 (der vorzeichenbehaftete 32-bit-Wert) nicht abgebildet. Dies ist absichtlich: (uid_t) -1 wird von einer Reihe von Schnittstellen (z.B. setreuid(2)) dazu verwandt, >>keine Benutzerkennung<< festzulegen. Da (uid_t) -1 nicht abgebildet und unbenutzbar ist, wird sichergestellt, dass es keine Verwirrung bei der Verwendung dieser Schnittstellen gibt. Definieren von Benutzer- und Gruppenkennungsabbildungen; Schreiben in uid_map und gid_map Nach der Erstellung eines neuen Benutzernamensraumes kann die Datei uid_map von einem der Prozesse in dem Namensraum einmalig geschrieben werden, um die Abbildung der Benutzerkennungen in dem neuen Benutzernamensraum zu definieren. Jeder Versuch, mehr als einmal in eine Datei uid_map in einem Benutzernamensraum zu schreiben, schlagt mit dem Fehler EPERM fehl. Ahnliche Regeln gelten fur Dateien gid_map. Die in uid_map (gid_map) geschriebenen Zeilen mussen die folgenden Gultigkeitsregeln erfullen: o Die drei Felder mussen gultige Zahlen sein und das letzte Feld muss grosser als 0 sein. o Zeilen werden durch einen Zeilenumbruch beendet. o Es gibt eine Beschrankung bezuglich der Anzahl der Zeilen in der Datei. In Linux 4.14 und alter war diese Beschrankung (willkurlich) auf 5 Zeilen gesetzt. Seit Linux 4.15 ist diese Beschrankung 340 Zeilen. Zusatzlich muss die Anzahl an in diese Datei geschriebenen Bytes kleiner als die Seitengrosse des Systems sein und das Schreiben muss am Anfang der Datei beginnen (d.h. lseek(2) und pwrite(2) konnen nicht zum Schreiben an einen von Null verschiedenen Versatz in der Datei verwandt werden). o Die Bereiche der Benutzerkennungen (Gruppenkennungen), die in den einzelnen Zeilen angegeben sind, durfen sich nicht gegenseitig uberlappen. In der anfanglichen Implementierung (Linux 3.8) wurde diese Anforderung durch eine simplistische Implementierung erfullt, die weitere Einschrankungen auferlegte, dass die Werte sowohl in Feld 1 als auch Feld 2 von aufeinanderfolgenden Zeilen in aufsteigender numerischer Reihenfolge sein mussten, womit andernfalls gultige Abbildungen nicht erstellt werden konnten. Linux 3.9 und neuer korrigierte diese Beschrankung und erlaubte jede Kombination von nichtuberlappenden Abbildungen. o Mindestens eine Zeile muss in die Datei geschrieben werden. Schreibvorgange, die die obigen Regeln verletzen, schlagen mit dem Fehler EINVAL fehl. Damit ein Prozess in die Datei /proc/PID/uid_map (/proc/PID/gid_map) schreiben kann, mussen alle der folgenden Berechtigungsanforderungen erfullt sein: o Der schreibende Prozess muss uber die Capability CAP_SETUID (CAP_SETGID) des Benutzernamensraums des Prozeses PID verfugen. o Der schreibende Prozess muss entweder in dem Benutzernamensraum des Prozesses PID oder in dem Vorgangernamensraum des Prozesses PID sein. o Die abgebildeten Benutzerkennungen (Gruppenkennungen) mussen wiederum eine Abbildung in dem Vorganger-Benutzernamensraum haben. o Falls die Aktualisierung von /proc/PID/uid_map eine Abbildung erstellt, die die UID 0 in dem Vorgangernamensraum abbildet, dann muss eine der folgenden Bedingungen wahr sein: (a) Falls der schreibende Prozess im Vorganger-Benutzernamensraum liegt, dann muss er uber die Capability CAP_SETFCAP in diesem Benutzernamensraum verfugen; oder (b) falls der schreibende Prozess in dem nachfolgenden Benutzernamensraum liegt, dann muss der Prozess, der den Benutzernamensraum erstellte, uber die Capability CAP_SETFCAP verfugen, als der Benutzernamensraum erstellt wurde. Diese Regel gibt es seit Linux 5.12. Sie beseitigt einen alteren Sicherheitsfehler, durch den ein UID-0-Prozess ohne die Capability CAP_SETFCAP (die zum Erstellen eines Programms mit Datei-Capabilitys im Namensraum benotigt wird, wie das in capabilities(7) beschrieben ist), trotzdem ein solches Programm erstellen konnte, indem es Folgendes durchfuhrte: (1) Erstellung eines neuen Benutzernamensraums mit der Identitatsabbildung (d.h. UID 0 in dem neuen Benutzernamensraum wird auf UID 0 im Vorgangernamensraum abgebildet), so dass UID 0 in beiden Namensraumen aquivalent zu der gleichen Root-Benutzerkennung ist. (2) Da der Nachfolgerprozess uber die Capability CAP_SETFCAP verfugt, konnte er ein Programm mit den Datei-Capabilitys im Namensraum erstellen, die auch im Vorgangernamensraum wirksam waren (da die Root-Benutzerkennungen in beiden Namensraumen identisch sind). o Einer der folgenden zwei Falle trifft zu: (a) Entweder verfugt der schreibende Prozess uber die Capability CAP_SETUID (CAP_SETGID) in dem Vorgangernamensraum. o Es gelten keine weiteren Einschrankungen; der Prozess kann Abbildungen auf beliebige Benutzerkennungen (Gruppenkennungen) im Vorgangernamensraum durchfuhren. (b) Oder es gelten alle der folgenden Beschrankungen: o Die in uid_map (gid_map) geschriebenen Daten mussen aus einer einzelnen Zeile bestehen, die die effektive Benutzerkennung (Gruppenkennung) des schreibenden Prozesses in dem Vorgangernamensraum auf eine Benutzerkennung (Gruppenkennung) in den Benutzernamensraum abbildet. o Der schreibende Prozess muss die gleiche effektive Benutzerkennung wie der Prozess haben, der den Benutzernamensraum erstellte. o Im Falle von gid_map muss zuerst die Verwendung des Systemaufrufs setgroups(2) verboten werden, indem >>deny<< in die Datei /proc/PID/setgroups geschrieben wird (siehe unten), bevor in gid_map geschrieben wird. Schreibaktionen, die die obigen Regeln verletzen, werden mit EPERM fehlschlagen. Projektkennungsabbildung: projid_map Ahnlich zu Benutzer- und Gruppenkennungsabbildungen ist es moglich, eine Projektkennungsabbildung fur einen Benutzernamensraum zu erstellen. (Projektkennungen werden fur Plattenkontingente verwandt, siehe setquota(8) und quotactl(2).) Projektkennungsabbildungen werden durch Schreiben in die Datei /proc/PID/projid_map definiert (vorhanden seit Linux 3.7). Die Gultigkeitsregeln fur das Schreiben in die Datei /proc/PID/projid_map sind wie beim Schreiben in die Datei uid_map; Verletzung dieser Regeln fuhrt beim write(2) zum Fehlschlag EINVAL. Die Erlaubnisregeln fur das Schreiben in die Datei /proc/PID/projid_map sind wie folgt: o Der schreibende Prozess muss entweder in dem Benutzernamensraum des Prozesses PID oder in dem Vorgangernamensraum des Prozesses PID sein. o Die abgebildeten Projektkennungen mussen wiederum eine Abbildung im Vorgangernamensraum haben. Verletzung dieser Regeln fuhrt dazu, dass write(2) mit EPERM fehlschlagt. Wechselwirkung mit Systemaufrufen, die Prozessbenutzerkennungen oder -gruppenkennungen andern In einem Benutzernamensraum, in dem die Datei uid_map noch nicht geschrieben wurde, werden die Systemaufrufe, die die Benutzerkennung andern, fehlschlagen. Ahnlich werden die Systemaufrufe, die die Gruppenkennungen andern, fehlschlagen, falls die Datei gid_map noch nicht geschrieben wurde. Nachdem die Dateien uid_map und gid_map geschrieben wurden, konnen nur die abgebildeten Werte in Systemaufrufen verwandt werden, die die Benutzer- und Gruppenkennungen andern. Fur Benutzerkennungen sind die relevanten Systemaufrufe unter anderem setuid(2), setfsuid(2), setreuid(2) und setresuid(2). Fur Gruppenkennungen sind die relevanten Systemaufrufe unter anderem setgid(2), setfsgid(2), setregid(2), setresgid(2) und setgroups(2). Durch Schreiben von >>deny<< in die Datei /proc/PID/setgroups vor dem Schreiben von /proc/PID/gid_map wird setgroups(2) in einem Benutzernamensraum dauerhaft deaktiviert und erlaubt Schreiben von /proc/PID/gid_map, ohne uber die Capability CAP_SETGID im Vorgangernamensraum zu verfugen. Die Datei /proc/PID/setgroups Die Datei /proc/PID/setgroups zeigt die Zeichenkette >>allow<<, falls Prozesse in dem Benutzernamensraum, der den Prozess PID enthalt, die Erlaubnis haben, den Systemaufruf setgroups(2) einzusetzen. Sie zeigt >>deny<< an, falls setgroups(2) in diesem Benutzernamensraum nicht erlaubt ist. Beachten Sie, dass Aufrufe von setgroups(2) auch nicht erlaubt sind, falls /proc/PID/gid_map noch nicht gesetzt wurde, unabhangig von dem Wert der Datei /proc/PID/setgroups (und unabhangig von den Capabilitys des Prozesses). Ein privilegierter Prozess (einer mit der Capability CAP_SYS_ADMIN in dem Namensraum) darf eine der Zeichenketten >>allow<< oder >>deny<< in diese Datei schreiben, bevor eine Gruppenkennungsabbildung fur diesen Benutzernamensraum in die Datei /proc/PID/gid_map geschrieben wird. Durch Schreiben der Zeichenkette >>deny<< wird jedem Prozess in diesem Benutzernamensraum der Einsatz von setgroups(2) verboten. Die Essenz der in den vorhergehenden Absatzen beschriebenen Beschrankungen ist, dass das Schreiben in /proc/PID/setgroups nur so lange erlaubt ist, wie setgroups(2) nicht erlaubt ist, da /proc/PID/gid_map noch nicht gesetzt wurde. Damit wird sichergestellt, dass ein Prozess nicht von einem Zustand, bei dem setgroups(2) erlaubt ist, zu einem Zustand, bei dem setgroups(2) verboten ist, ubergehen kann; ein Prozess kann nur von setgroups(2) nicht erlaubt zu setgroups(2) erlaubt ubergehen. Der Vorgabewert fur diese Datei in dem anfanglichen Namensraum ist >>allow<<. Sobald /proc/PID/gid_map geschrieben wurde (wodurch setgroups(2) in dem Benutzernamensraum aktiviert wird), ist es nicht mehr moglich, setgroups(2) durch Schreiben von >>deny<< in /proc/PID/setgroups zu verbieten (das Schreiben schlagt mit EPERM fehl). Ein Nachfolgernamensraum erbt die Einstellungen /proc/PID/setgroups von seinem Vorganger. Falls die Datei setgroups den Wert >>deny<< enthalt, dann kann der Systemaufruf setgroups(2) in diesem Namensraum nachfolgend nicht mehr aktiviert werden (durch Schreiben von >>allow<< in die Datei). (Versuche, dies durchzufuhren, schlagen mit EPERM fehl.) Diese Beschrankung wird auch an alle Nachfolgerbenutzernamensraume dieses Benutzernamensraums weitergeleitet. Die Datei /proc/PID/setgroups wurde in Linux 3.19 hinzugefugt; allerdings wurde sie auch auf viele fruhere stabile Kernel ruckportiert, da sie ein Sicherheitsproblem adressiert. Das Problem betraf Dateien mit Berechtigungen wie >>rwx---rwx<<. Diese Dateien geben der >>Gruppe<< weniger Berechtigungen als sie >>anderen<< geben. Das bedeutet, dass die Abgabe von Gruppen mittels setgroups(2) einem Prozess Dateizugriff erlauben konnte, den er vorher nicht hatte. Vor der Existenz von Benutzernamensraumen fuhrte dies zu keine Sorgen, da nur ein privilegierter Prozess (einer mit der Capability CAP_SETGID) setgroups(2) aufrufen konnte. Mit der Einfuhrung von Benutzernamensraumen wurde es fur einen nicht privilegierten Prozess allerdings moglich, einen neuen Namensraum zu erstellen, in dem der Benutzer alle Privilegien hatte. Dies ermoglichte es dann vorher nicht privilegierten Benutzern Gruppen abzugeben und damit Dateizugriff zu erlangen, den sie vorher nicht hatten. Die Datei /proc/PID/setgroups wurde hinzugefugt, um dieses Sicherheitsproblem zu adressieren, indem jeder Pfad fur einen nicht privilegierten Prozess, Gruppen mit setgroups(2) abzugeben, verboten wurde. Nicht abgebildete Benutzer- und Gruppenkennungen Es gibt verschiedene Stellen, an denen nicht abgebildete Benutzerkennungen (Gruppenkennungen) im Anwendungsraum offengelegt werden konnen. Beispielsweise konnte der erste Prozess in einem neuen Benutzernamensraum getuid(2) aufrufen, bevor eine Benutzerkennungsabbildung fur den Namensraum definiert wurde. In den meisten solcher Falle wird eine nicht abgebildete Benutzerkennung in die Uberlauf-Benutzerkennung (Gruppenkennung) konvertiert; der Vorgabewert fur die Uberlauf-Benutzerkennung (Gruppenkennung) ist 65534. Siehe die Beschreibung von /proc/sys/kernel/overflowuid und /proc/sys/kernel/overflowgid in proc(5). Zu den Fallen, in denen nicht abgebildete Benutzerkennungen auf diese Art abgebildet werden, gehoren Systemaufrufe, die Benutzerkennungen zuruckliefern (getuid(2), getgid(2) und ahnliche), Benutzerberechtigungen, die uber ein UNIX-Domain-Socket ubergeben werden, Benutzerberechtigungen, die von stat(2), waitid(2) und den System-V-IPC->>ctl<<-IPC_STAT-Aktionen zuruckgeliefert werden, Benutzerberechtigungen, die mittels /proc/PID/status und den Dateien in /proc/sysvipc/* offengelegt werden, Benutzerberechtigungen, die uber das Feld si_uid in dem mit einem Signal siginfo_t empfangenen Feld zuruckgeliefert werden (siehe sigaction(2)), Benutzerberechtigungen, die in die Prozessbuchhaltungsdatei geschrieben werden (siehe acct(5)) und Benutzerberechtigungen, die mit POSIX-Nachrichtenwarteschlangen-Benachrichtigungen zuruckgeliefert werden (siehe mq_notify(3)). Es gibt einen erwahnenswerten Fall, bei dem nicht abgebildete Benutzer- und Gruppenkennungen nicht in die entsprechende Uberlaufkennung konvertiert werden. Beim Betrachten einer Datei uid_map oder gid_map, bei der es keine Abbildung fur das zweite Feld gibt, wird das Feld als 4294967295 (-1 als eine vorzeichenlose Ganzzahl) dargestellt. Dateizugriff Um Berechtigungen zu bestimmen, wenn ein nicht privilegierter Prozess auf eine Datei zugreift, werden die Prozessberechtigungen (UID, GID) und die Dateiberechtigungen letztendlich auf die zuruckabgebildet, die sie im anfanglichen Benutzernamensraum waren und dann verglichen, um die Berechtigungen zu bestimmen, die der Prozess auf die Datei hat. Das gleiche trifft auch fur andere Objekte zu, die das Zugriffsmodell mit Benutzerberechtigungen sowie Berechtigungsmasken einsetzen, wie System-V-IPC-Objekte. Aktionen mit Datei-bezogenen Capabilitys Bestimmte Capabilitys erlauben es einem Prozess, verschiedene, durch den Kernel durchgesetzte Beschrankungen zu umgehen, wenn Aktionen auf Dateien durchgefuhrt werden, die anderen Benutzern oder Gruppen gehoren. Diese Capabilitys sind CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER und CAP_FSETID. Innerhalb eines Benutzernamensraumes erlauben diese Capabilitys einem Prozess, die Regeln zu umgehen, falls der Prozess uber die relevante Capability uber die Datei verfugt. Das bedeutet: o Der Prozess hat die relevante effektive Capability in seinem eigenen Benutzernamensraum; und o die Benutzer- und Gruppenkennung der Datei habe beide gultige Abbildungen in dem Benutzernamensraum. Die Capability CAP_FOWNER wird etwas besonders behandelt: sie erlaubt einem Prozess, die entsprechenden Regeln zu umgehen, solange zumindest die Benutzerkennung der Datei uber eine Abbildung in dem Benutzernamensraum verfugt (d.h. die Gruppenkennung der Datei benotigt keine gultige Abbildung). Set-user-ID- und set-group-ID-Programme Wenn ein Prozess innerhalb eines Benutzernamensraums ein set-user-ID- (set-group-ID)-Programm ausfuhrt, wird die effektive Benutzer- (Gruppen-)Kennung des Prozesses innerhalb des Namensraums auf denjenigen Wert geandert, der fur die Benutzer- (Gruppen)kennung der Datei abgebildet ist. Falls allerdings entweder die Benutzer- oder die Gruppenkennung der Datei uber keine Abbildung innerhalb des Namensraums verfugt, wird das set-user-ID- (set-group-ID-)Bit ohne Ruckmeldung ignoriert: das neue Programm wird ausgefuhrt, aber die effektive Benutzer- (Gruppen-)Kennung des Prozesses bleibt unverandert. (Dies spiegelt die Semantik bei der Ausfuhrung eines set-user-ID- oder set-group-ID-Programmes wider, das sich auf einem Dateisystem befindet, das mit dem Schalter MS_NOSUID eingehangt wurde, wie dies in mount(2) beschrieben ist.) Verschiedenes Wenn die Benutzer- und Gruppenkennungen eines Prozesses uber ein UNIX-Domain-Socket an einen Prozess in einem anderen Benutzernamensraum ubergeben werden (siehe die Beschreibung von SCM_CREDENTIALS in unix(7)), werden sie in die entsprechenden Werte der Benutzer- und Gruppenkennungsabbildungen des empfangenen Prozesses ubersetzt. STANDARDS Linux. ANMERKUNGEN Uber die Jahre wurden eine Reihe von Funktionalitaten zu dem Linux-Kernel hinzugefugt, die nur privilegierten Benutzern verfugbar gemacht wurden, da sie moglicherweise set-user-ID-root-Anwendungen durcheinander bringen konnten. Im Allgemeinen wird es sicher, einem Root-Benutzer in einem Benutzernamensraum die Verwendung dieser Funktionalitaten zu erlauben, da es unmoglich ist, mehr Privilegien zu erlangen, als der Root-Benutzer innerhalb eines Benutzernamensraumes hat, wahrend der Prozess im Benutzernamensraum ist. Globaler Root Der Ausdruck >>Globaler Root<< wird manchmal als Abkurzung fur die Benutzerkennung 0 im anfanglichen Benutzernamensraum verwandt. Verfugbarkeit Die Verwendung von Benutzernamensraumen benotigt einen Kernel, der mit der Option CONFIG_USER_NS konfiguriert ist. Benutzernamensraume benotigen die Unterstutzung in einer ganzen Reihe von Subsystemen im Kernel. Wird ein nicht unterstutztes Subsystem in den Kernel konfiguriert, dann ist es nicht moglich, die Unterstutzung von Benutzernamensraumen zu konfigurieren. Seit Linux 3.8 unterstutzen die wichtigsten Subsysteme Benutzernamensraume, aber eine Reihe von Dateisystemen hatten noch nicht die benotigte Infrastruktur, um Benutzer- und Gruppenkennungen zwischen Benutzernamensraumen abzubilden. Linux 3.9 fugte die benotigte Infrastruktur fur viele der verbliebenen, nicht unterstutzten Dateisysteme (Plan 9 (9P), Andrew File System (AFS), Ceph, CIFS, CODA, NFS und OCFS2) hinzu. Linux 3.12 fugte Unterstutzung fur das letzte grosse verbliebene und nicht unterstutzte Dateisystem hinzu: XFS. BEISPIELE Das nachfolgende Programm ist zum Experimentieren mit Benutzernamensraumen sowie anderen Arten von Namensraumen gedacht. Es erstellt einen Namensraum, wie er uber die Befehlszeilenoptionen angegeben ist, und fuhrt dann innerhalb dieser Namensraume einen Befehl aus. Die Kommentare und die Funktion usage() innerhalb des Programmes bieten eine vollstandige Erklarung des Programms. Die nachfolgende Shell-Sitzung zeigt seine Verwendung. Zuerst schauen wir auf die Laufzeitumgebung: $ uname -rs # Benotigt Linux 3.8 oder neuer Linux 3.8.0 $ id -u # Ausfuhrung als nicht privilegierter Benutzer 1000 $ id -g 1000 Jetzt wird eine neue Shell in neuen Benutzer- (-U), Einhange- (-m) und PID- (-p) Namensraumen gestartet, wobei innerhalb des Benutzernamensraums die Benutzerkennung (-M) und Gruppenkennung (-G) 1000 auf 0 abgebildet wird: $ ./userns_child_exec -p -m -U -M '0 1000 1' -G '0 1000 1' bash Diese Shell hat PID 1, da sie der erste Prozess in dem neuen PID-Namensraum ist: bash$ echo $$ 1 Wird ein neues Dateisystem /proc eingehangt und alle in dem neuen PID-Namensraum sichtbaren Prozesse aufgelistet, kann gesehen werden, dass die Shell keinerlei Prozesse ausserhalb des PID-Namensraumes sehen kann: bash$ mount -t proc proc /proc bash$ ps ax PID TTY STAT TIME COMMAND 1 pts/3 S 0:00 bash 22 pts/3 R+ 0:00 ps ax Innerhalb des Benutzernamensraumes hat die Shell die Benutzer- und Gruppenkennung 0 und eine vollstandige Menge an erlaubten und effektiven Capabilitys: bash$ cat /proc/$$/status | egrep '^[UG]id' Uid: 0 0 0 0 Gid: 0 0 0 0 bash$ cat /proc/$$/status | egrep '^Cap(Prm|Inh|Eff)' CapInh: 0000000000000000 CapPrm: 0000001fffffffff CapEff: 0000001fffffffff Programmquelltext /* userns_child_exec.c Lizenziert unter der GNU General Public License v2 oder neuer Erzeugt einen Kindprozess, der einen Shell-Befehl in einem oder mehreren neuen Namensraumen ausfuhrt; erlaubt UID- und GID-Abbildungen anzugeben, wenn ein Benutzernamensraum erstellt wird */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include struct child_args { char **argv; /* Vom Kind auszufuhrender Befehl, mit Argumenten */ int pipe_fd[2]; /* Zur Sychronisation Eltern/Kind verwandte Pipe */ }; static int verbose; static void usage(char *pname) { fprintf(stderr, "Aufruf: %s [Optionen] Bef [Arg]\n\n", pname); fprintf(stderr, "Erstellt einen Kindprozess, der einen Shellbefehl " "in einem neuen Benutzernamensraum ausfuhrt\n" "und moglicherweise auch anderen neuen Namensraumen.\n\n"); fprintf(stderr, "Optionen konnen sein:\n\n"); #define fpe(str) fprintf(stderr, " %s", str); fpe("-i Neuer IPC-Namensraum\n"); fpe("-m Neuer Einhange-Namensraum\n"); fpe("-n Neuer Netzwerk-Namensraum\n"); fpe("-p Neuer PID-Namensraum\n"); fpe("-u Neuer UTS-Namensraum\n"); fpe("-U Neuer Benutzernamensraum\n"); fpe("-M uid_map Angabe einer UID-Abbildung fur Benutzernamensraum\n"); fpe("-G gid_map Angabe einer GID-Abbildung fur Benutzernamensraum\n"); fpe("-z Benutzer-UID und -GID auf 0 im Benutzernamensraum abbilden\n"); fpe(" (aquivalent zu: -M '0 1' -G '0 1')\n"); fpe("-v Anzeige ausfuhrlicher Meldungen\n"); fpe("\n"); fpe("Falls -z, -M oder -G angegeben wird, ist -U verpflichtend.\n"); fpe("Es ist nicht erlaubt, sowohl -z als auch entweder -M oder -G anzugeben.\n"); fpe("\n"); fpe("Abbildungszeichenketten fur -M und -G bestehen aus Datensatzen der folgenden Form:\n"); fpe("\n"); fpe(" Namensrauminterne-Kennung Namensraumexterne-Kennung Lange\n"); fpe("\n"); fpe("Eine Abbildungszeichenkette kann mehrere Datensatze enthalten," " getrennt durch Kommata;\n"); fpe("die Kommata werden vor dem Schreiben in die Abbildungsdateien durch" " Zeilenumbruche ersetzt.\n"); exit(EXIT_FAILURE); } /* Aktualisiert die Abbildungsdatei >>map_file<< mit dem in >>mapping<< bereitgestellten Wert, einer Zeichenkette, die eine UID- oder GID- Abbildung definiert. Eine UID- oder GID-Abbildung besteht aus einem oder mehreren, durch Zeilenumbruche getrennten Datensatzen der folgenden Form: Namensrauminterne-Kennung Namensraumexterne-Kennung Lange Fur die Befehlszeile zu verlangen, dass Zeichenketten mit Zeilenumbruchen bereitgestellt werden, ist naturlich unbequem. Daher erlauben wir die Verwendung von Kommata zur Begrenzung von Datensatzen in dieser Zeichenkette und ersetzen sie vor dem Schreiben in die Datei durch Zeilenumbruche. */ static void update_map(char *mapping, char *map_file) { int fd; size_t map_len; /* Lange der >>mapping<< */ /* Kommata durch Zeilenumbruche in Abbildungszeichenkette ersetzen. */ map_len = strlen(mapping); for (size_t j = 0; j < map_len; j++) if (mapping[j] == ',') mapping[j] = '\n'; fd = open(map_file, O_RDWR); if (fd == -1) { fprintf(stderr, "FEHLER: open %s: %s\n", map_file, strerror(errno)); exit(EXIT_FAILURE); } if (write(fd, mapping, map_len) != map_len) { fprintf(stderr, "FEHLER: write %s: %s\n", map_file, strerror(errno)); exit(EXIT_FAILURE); } close(fd); } /* Linux 3.19 anderte die Handhabung von setgroups(2) und die Datei >>gid_map<<, um ein Sicherheitsproblem zu adressieren. Das Problem erlaubte *nicht privilegierten* Benutzern einen Benutzernamensraum einzusetzen, um Gruppen abzugeben. Das Fazit der 3.19er Anderung ist, dass die Verwendung des Systemaufrufs setgroups() in diesem Benutzernamensraum zuerst durch Schreiben von >>deny<< in eine der Dateien /proc/PID/setgroups fur diesen Namensraum erfolgen muss, damit die Datei >>gid_maps<< aktualisert wird. Das ist der Zweck der folgenden Funktion. */ static void proc_setgroups_write(pid_t child_pid, char *str) { char setgroups_path[PATH_MAX]; int fd; snprintf(setgroups_path, PATH_MAX, "/proc/%jd/setgroups", (intmax_t) child_pid); fd = open(setgroups_path, O_RDWR); if (fd == -1) { /* Vielleicht sind wir auf einem System, das /proc/PID/setgroups nicht unterstutzt. Dann wird diese Datei nicht existieren und das System wird nicht die Beschrankungen erzwingen, die Linux 3.19 hinzugefugt hat. Das ist OK, wir brauchen nichts zu machen, damit >>gid_map<< aktualisiert wird. Falls allerdings der Fehler von open() sich von ENOENT unterscheidet (der in diesem Fall zu erwarten ist), informieren wir den Benutzer. */ if (errno != ENOENT) fprintf(stderr, "FEHLER: open %s: %s\n", setgroups_path, strerror(errno)); return; } if (write(fd, str, strlen(str)) == -1) fprintf(stderr, "FEHLER: write %s: %s\n", setgroups_path, strerror(errno)); close(fd); } static int /* Funktion fur geklontes Kind starten */ childFunc(void *arg) { struct child_args *args = arg; char ch; /* Warten, bis der Elternprozess seine UID- und GID-Abbildungen aktualisiert hat. Siehe den Kommentar in main(). Wir warten, bis auf einer Pipe das Dateiende kommt, die vom Elternprozess geschlossen wird, sobald er seine Abbildungen aktualisiert hat. */ close(args->pipe_fd[1]); /* Unseren Deskriptor fur das Ende des Schreibens schliessen, so dass wir EOF sehen, wenn der Elternprozess seinen Deskriptor schliesst. */ if (read(args->pipe_fd[0], &ch, 1) != 0) { fprintf(stderr, "Fehler im Kind: Lesen von der Pipe lieferte != 0\n"); exit(EXIT_FAILURE); } close(args->pipe_fd[0]); /* Einen Shell-Befehl ausfuhren. */ printf("Gleich wird exec %s ausgefuhrt\n", args->argv[0]); execvp(args->argv[0], args->argv); err(EXIT_FAILURE, "execvp"); } #define STACK_SIZE (1024 * 1024) static char child_stack[STACK_SIZE]; /* Platz fur den Stack des Kindes */ int main(int argc, char *argv[]) { int flags, opt, map_zero; pid_t child_pid; struct child_args args; char *uid_map, *gid_map; const int MAP_BUF_SIZE = 100; char map_buf[MAP_BUF_SIZE]; char map_path[PATH_MAX]; /* Befehlszeilenoptionen auswerten. Das anfangliche >>+<<-Zeichen in dem abschliessenden getopt()-Argument verhindert GNU-artige Vertauschungen der Befehlszeilenoptionen. Das ist nutzlich, da manchmal der von diesem Programm selbst ausgefuhrte >>Befehl<< uber Befehlszeilenoptionen verfugt. Wir wollen nicht, dass getopt() solche als Optionen fur dieses Programm behandelt. */ flags = 0; verbose = 0; gid_map = NULL; uid_map = NULL; map_zero = 0; while ((opt = getopt(argc, argv, "+imnpuUM:G:zv")) != -1) { switch (opt) { case 'i': flags |= CLONE_NEWIPC; break; case 'm': flags |= CLONE_NEWNS; break; case 'n': flags |= CLONE_NEWNET; break; case 'p': flags |= CLONE_NEWPID; break; case 'u': flags |= CLONE_NEWUTS; break; case 'v': verbose = 1; break; case 'z': map_zero = 1; break; case 'M': uid_map = optarg; break; case 'G': gid_map = optarg; break; case 'U': flags |= CLONE_NEWUSER; break; default: usage(argv[0]); } } /* -M oder -G ohne -U ist sinnlos */ if (((uid_map != NULL || gid_map != NULL || map_zero) && !(flags & CLONE_NEWUSER)) || (map_zero && (uid_map != NULL || gid_map != NULL))) usage(argv[0]); args.argv = &argv[optind]; /* Wir verwenden eine Pipe, um den Eltern- und Kindprozess zu synchronisieren, damit sichergestellt wird, dass der Elternprozess die UID- und GID-Abbildungen einrichtet, bevor der Kindprozess execve() aufruft. Dies stellt sicher, dass das Kind seine Capabilitys wahrend des execve() erhalt, wenn der typische Fall vorliegt, dass wir mochten, dass die effektive Benutzerkennung des Kindprozesses auf 0 in dem neuen Benutzernamensraum abgebildet wird. Ohne diese Synchronisation wurde der Kindprozess seine Capabilitys verlieren, falls es ein execve() mit einer von Null verschiedenen Benutzerkennung durchfuhren wurde (siehe die Handbuchseite capabilities(7) fur Details des Ubergangs der Capabilitys eines Prozesses wahrend execve()). */ if (pipe(args.pipe_fd) == -1) err(EXIT_FAILURE, "pipe"); /* Den Kindprozess in dem oder den neuen Namensraum/-raumen erstellen. */ child_pid = clone(childFunc, child_stack + STACK_SIZE, flags | SIGCHLD, &args); if (child_pid == -1) err(EXIT_FAILURE, "clone"); /* Elternprozess fallt bis hierher durch. */ if (verbose) printf("%s: PID des durch clone() erstellten Kindprozesses lautet %jd\n", argv[0], (intmax_t) child_pid); /* Die UID- und GID-Abbildungen in dem Kindprozess aktualisieren. */ if (uid_map != NULL || map_zero) { snprintf(map_path, PATH_MAX, "/proc/%jd/uid_map", (intmax_t) child_pid); if (map_zero) { snprintf(map_buf, MAP_BUF_SIZE, "0 %jd 1", (intmax_t) getuid()); uid_map = map_buf; } update_map(uid_map, map_path); } if (gid_map != NULL || map_zero) { proc_setgroups_write(child_pid, "deny"); snprintf(map_path, PATH_MAX, "/proc/%jd/gid_map", (intmax_t) child_pid); if (map_zero) { snprintf(map_buf, MAP_BUF_SIZE, "0 %ld 1", (intmax_t) getgid()); gid_map = map_buf; } update_map(gid_map, map_path); } /* Das Schreibe-Ende der Pipe schliessen, um dem Kindprozess zu signalisieren, dass wir die UID- und GID-Abbildungen aktualisiert haben. */ close(args.pipe_fd[1]); if (waitpid(child_pid, NULL, 0) == -1) /* Warten auf Kindprozess */ err(EXIT_FAILURE, "waitpid"); if (verbose) printf("%s: beende\n", argv[0]); exit(EXIT_SUCCESS); } SIEHE AUCH newgidmap(1), newuidmap(1), clone(2), ptrace(2), setns(2), unshare(2), proc(5), subgid(5), subuid(5), capabilities(7), cgroup_namespaces(7), credentials(7), namespaces(7), pid_namespaces(7) Die Kernelquelldatei Documentation/admin-guide/namespaces/resource-control.rst. UBERSETZUNG Die deutsche Ubersetzung dieser Handbuchseite wurde von Helge Kreutzmann erstellt. Diese Ubersetzung ist Freie Dokumentation; lesen Sie die GNU General Public License Version 3 oder neuer bezuglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG ubernommen. Wenn Sie Fehler in der Ubersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die Mailingliste der Ubersetzer . Linux man-pages 6.9.1 15. Juni 2024 user_namespaces(7)