.\" -*- coding: UTF-8 -*- .\" Copyright (c) 2013, 2014 by Michael Kerrisk .\" and Copyright (c) 2012, 2014 by Eric W. Biederman .\" .\" %%%LICENSE_START(VERBATIM) .\" Permission is granted to make and distribute verbatim copies of this .\" manual provided the copyright notice and this permission notice are .\" preserved on all copies. .\" .\" Permission is granted to copy and distribute modified versions of this .\" manual under the conditions for verbatim copying, provided that the .\" entire resulting derived work is distributed under the terms of a .\" permission notice identical to this one. .\" .\" Since the Linux kernel and libraries are constantly changing, this .\" manual page may be incorrect or out-of-date. The author(s) assume no .\" responsibility for errors or omissions, or for damages resulting from .\" the use of the information contained herein. The author(s) may not .\" have taken the same level of care in the production of this manual, .\" which is licensed free of charge, as they might when working .\" professionally. .\" .\" Formatted or processed versions of this manual, if unaccompanied by .\" the source, must acknowledge the copyright and authors of this work. .\" %%%LICENSE_END .\" .\" .\"******************************************************************* .\" .\" This file was generated with po4a. Translate the source file. .\" .\"******************************************************************* .TH USER_NAMESPACES 7 "1. November 2020" Linux Linux\-Programmierhandbuch .SH BEZEICHNUNG user_namespaces \- Überblick über Benutzernamensräume in Linux .SH BESCHREIBUNG Für einen Überblick über Namensräume, siehe \fBnamespaces\fP(7). .PP .\" FIXME: This page says very little about the interaction .\" of user namespaces and keys. Add something on this topic. .\" .\" ============================================================ .\" Benutzernamensräume isolieren sicherheitsrelevante Kennzeichner und Attribute, insbesondere Benutzer\- und Gruppenkennungen (siehe \fBcredentials\fP(7)), das Wurzelverzeichnis, Schlüssel (siehe \fBkeyrings\fP(7)) und Capabilitys (siehe \fBcapabilities\fP(7)). Die Benutzer\- und Gruppenkennung eines Prozesses kann innerhalb und außerhalb eines Benutzernamensraums verschieden sein. Insbesondere kann ein Prozess eine normale, nicht privilegierte Benutzerkennung außerhalb eines Benutzernamensraums haben, während er gleichzeitig eine Benutzerkennung 0 innerhalb des Namensraums hat; mit anderen Worten, der Prozess hat volle Privilegien für Aktionen innerhalb des Benutzernamensraums, ist aber für Aktionen außerhalb des Namensraums nicht privilegiert. .SS "Verschachtelte Namensräume, Namensraum\-Mitgliedschaft" Benutzernamensräume können verschachtelt werden, das bedeutet, dass jeder Benutzernamensraum\(emaußer dem anfänglichen (»Wurzel\-«)Namensraum\(emüber einen Vorgängernamensraum verfügt und keinen oder mehrere Nachfolgernamensräume haben kann. Der Vorgängernamensraum ist der Benutzernamensraum des Prozesses, der den Benutzernamensraum mittels eines Aufrufs von \fBunshare\fP(2) oder \fBclone\fP(2) mit dem Schalter \fBCLONE_NEWUSER\fP erstellte. .PP .\" commit 8742f229b635bf1c1c84a3dfe5e47c814c20b5c8 .\" FIXME Explain the rationale for this limit. (What is the rationale?) (Seit Version 3.11) erzwingt der Kernel eine Begrenzung von 32 verschachtelten Stufen an Benutzernamensräumen. Aufrufe an \fBunshare\fP(2) oder \fBclone\fP(2), die zum Überschreiten dieser Begrenzung führen würden, schlagen mit dem Fehler \fBEUSERS\fP fehl. .PP Jeder Prozess ist Mitglied in genau einem Benutzernamensraum. Ein mit \fBfork\fP(2) oder \fBclone\fP(2) ohne den Schalter \fBCLONE_NEWUSER\fP erstellter Prozess ist ein Mitglied im gleichen Benutzernamensraum wie sein Elternprozess. Ein Prozess mit nur einem Thread kann einem anderen Benutzernamensraum mit \fBsetns\fP(2) beitreten, falls er über \fBCAP_SYS_ADMIN\fP in diesem Namensraum verfügt; wenn er dies durchführt, erlangt er den vollständigen Satz an Capabilitys in diesem Namensraum. .PP Ein Aufruf von \fBclone\fP(2) oder \fBunshare\fP(2) mit dem Schalter \fBCLONE_NEWUSER\fP führt dazu, dass der Kindprozess (für \fBclone\fP(2)) oder der Aufrufende (für \fBunshare\fP(2)) ein Mitglied des neuen, durch den Aufruf erstellten Benutzernamensraums wird. .PP .\" .\" ============================================================ .\" Die Aktion \fBNS_GET_PARENT\fP \fBioctl\fP(2) kann zum Erkennen der Vorgänger\-/Nachfolger\-Beziehung von Benutzernamensräumen verwandt werden; siehe \fBioctl_ns\fP(2). .SS Capabilitys Der durch \fBclone\fP(2) mit dem Schalter \fBCLONE_NEWUSER\fP erstellte Kindprozess beginnt mit einem vollständigen Satz an Capabilitys in dem neuen Benutzernamensraum. Entsprechend erlangt ein Prozess, der einen neuen Benutzernamensraum mittels \fBunshare\fP(2) erstellt oder ihm mittels \fBsetns\fP(2) beitritt, einen vollständigen Satz an Capabilitys in diesem Namensraum. Anderserseits hat dieser Prozess keine Capabilitys in dem Vorgänger\- (im Falle von \fBclone\fP(2)) oder vorhergehenden (im Falle von \fBunshare\fP(2) und \fBsetns\fP(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). .PP Beachten Sie, dass ein Aufruf von \fBexecve\fP(2) dazu führt, dass die Capabilitys eines Prozesses auf die normale Art und Weise erneut berechnet werden (siehe \fBcapabilities\fP(7)). Folglich wird der Prozess alle Capabilitys verlieren, außer er hat eine Benutzerkennung von 0 innerhalb des Namensraums oder die ausführbare Datei hat eine vererbbare Capability\-Maske, die nicht leer ist. Siehe die nachfolgende Diskussion von Benutzer\- und Gruppenkennungabbildung. .PP Ein Aufruf von \fBclone\fP(2) oder \fBunshare\fP(2) mit dem Schalter \fBCLONE_NEWUSER\fP oder ein Aufruf von \fBsetns\fP(2), der den Aufrufenden in einen anderen Benutzernamensraum verschiebt, setzt die Schalter »securebits« (siehe \fBcapabilities\fP(7)) im Kind (für \fBclone\fP(2)) oder dem Aufrufenden (für \fBunshare\fP(2) oder \fBsetns\fP(2)) auf ihre Vorgabewerte (alle Schalter deaktiviert). Beachten Sie, dass der Aufrufende nach einem Aufruf von \fBsetns\fP(2) keine Capabilitys in seinem ursprünglichen Benutzernamensraum mehr hat und es daher für einen Prozess nicht möglich ist, seine Schalter »securebits« zurückzusetzen und gleichzeitig seine Mitgliedschaft im Benutzernamensraum zu erhalten, indem ein Paar von \fBsetns\fP(2)\-Aufrufen verwandt wird, um sich in einen anderen Benutzernamensraum zu verschieben und dann zu seinem ursprünglichen Namensraum zurückzukehren. .PP Die Regeln zur Bestimmung, ob ein Prozess eine Capability in einem bestimmten Benutzernamensraum hat, sind wie folgt: .IP 1. 3 .\" In the 3.8 sources, see security/commoncap.c::cap_capable(): 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 könnte er ein set\-user\-ID\-Programm oder eine ausführbare Datei mit zugeordneten Datei\-Capabilitys ausführen. Zusätzlich könnte ein Prozess Capabilitys mittels der bereits beschriebenen Auswirkungen von \fBclone\fP(2), \fBunshare\fP(2) oder \fBsetns\fP(2) erlangen. .IP 2. Falls ein Prozess eine Capability in einem Benutzernamensraum hat, dann hat es diese Capability in allen nachfolgenden (und weiter entfernten Nachfolge\-) Namensräumen ebenfalls. .IP 3. .\" * The owner of the user namespace in the parent of the .\" * user namespace has all caps. .\" (and likewise associates the effective group ID of the creating process .\" with the namespace). .\" See kernel commit 520d9eabce18edfef76a60b7b839d54facafe1f9 for a fix .\" on this point .\" This includes the case where the process executes a set-user-ID .\" program that confers the effective UID of the creator of the namespace. .\" .\" ============================================================ .\" Wenn ein Benutzernamensraum erstellt wird, zeichnet der Kernel die effektive Benutzerkennung des erstellenden Prozesses als »Eigentümer« des Namensraums auf. Ein Prozess, der sich im Vorgänger des Benutzernamensraums befindet und dessen effektive Benutzerkennung auf die des Eigentümers des Namensraums passt, hat alle Capabilitys in diesem Namensraum. Dank der vorherigen Regel bedeutet dies, dass der Prozess auch über alle Capabilitys in allen weiteren entfernten nachfolgenden Benutzerräumen verfügt. Die Aktion \fBNS_GET_OWNER_UID\fP \fBioctl\fP(2) kann zum Ermitteln der Benutzerkennung des Eigentümers des Namensraums verwandt werden; siehe \fBioctl_ns\fP(2). .SS "Auswirkungen von Capabilitys innerhalb eines Benutzernamensraums" Hat ein Prozess eine Capability innerhalb eines Benutzernamensraums, dann darf er Aktionen nur auf Ressourcen anwenden (die Privilegien benötigen), die durch diesen Namensraum reguliert werden. Mit anderen Worten erlaubt eine Capability in einem Benutzernamensraum einem Prozess, privilegierte Aktionen auf Ressourcen durchzuführen, die durch (Nichtbenutzer\-)Namensräume gelenkt werden, die den Benutzernamensräumen gehören bzw. diesen zugeordnet sind (siehe den nächsten Unterabschnitt). .PP Auf der anderen Seite gibt es viele privilegierte Aktionen, die Ressourcen betreffen, die keinem Namensraumtyp zugeordnet sind, beispielsweise dem Ändern der Systemzeit (z.B. Kalender) (wird durch \fBCAP_SYS_TIME\fP reguliert), dem Laden eines Kernelmoduls (wird durch \fBCAP_SYS_MODULE\fP reguliert) und dem Erstellen eines Gerätes (wird durch \fBCAP_MKNOD\fP reguliert). Nur Prozesse, die über Privilegien in dem \fIursprünglichen\fP Benutzernamensraum verfügen, können solche Aktionen durchführen. .PP .\" fs_flags = FS_USERNS_MOUNT in kernel sources Wenn ein Prozess \fBCAP_SYS_ADMIN\fP innerhalb eines Namensraums hält, der den Einhängenamensraum des Prozesses besitzt, dann kann er Bind\-Einhängungen erstellen und die folgenden Arten an Dateisystemen einhängen: .PP .RS 4 .PD 0 .IP * 2 \fI/proc\fP (seit Linux 3.8) .IP * \fI/sys\fP (seit Linux 3.8) .IP * \fIdevpts\fP (seit Linux 3.9) .IP * \fBtmpfs\fP(5) (seit Linux 3.9) .IP * \fIramfs\fP (seit Linux 3.9) .IP * \fImqueue\fP (seit Linux 3.9) .IP * .\" commit b2197755b2633e164a439682fb05a9b5ea48f706 \fIbpf\fP (seit Linux 4.4) .PD .RE .PP Wenn ein Prozess \fBCAP_SYS_ADMIN\fP innerhalb eines Namensraums hält, 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 \fI"none,name="\fP eingehängt sind) einhängen. .PP Wenn ein Prozess \fBCAP_SYS_ADMIN\fP innerhalb eines Namensraums hält, der den PID\-Namensraum des Prozesses besitzt, dann kann er (seit Linux 3.8) \fI/proc\fP\-Dateisysteme einhängen. .PP .\" .\" ============================================================ .\" Beachten Sie, dass das Einhängen blockbasierter Dateisysteme nur von Prozessen erfolgen kann, die \fBCAP_SYS_ADMIN\fP in dem anfänglichen Benutzernamensraum enthalten. .SS "Wechselwirkung von Benutzernamensräumen und anderen Arten von Namensräumen" Seit Linux 3.8 können nicht privilegierte Prozesse Benutzernamensräume erstellen und andere Arten von Namensräumen können nur mit der Capability \fBCAP_SYS_ADMIN\fP im Benutzernamensraum des Aufrufenden erstellt werden. .PP Wenn ein Nichtbenutzer\-Namensraum erstellt wird, gehört 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, benötigen, dass der Prozess über die notwendigen Capabilitys in dem Benutzernamensraum verfügt, der den Nichtbenutzer\-Namensraum besitzt. .PP Falls \fBCLONE_NEWUSER\fP zusammen mit anderen Schaltern \fBCLONE_NEW*\fP in einem einzelnen Aufruf von \fBclone\fP(2) oder \fBunshare\fP(2) angegeben wird, wird garantiert, dass der Namensraum zuerst erstellt wird, und damit dem Kindprozess (\fBclone\fP(2)) oder dem aufrufenden Prozess (\fBunshare\fP(2)) Privilegien über den durch den Aufruf erstellten Namensraum gegeben wird. Daher ist es für einen nicht privilegierten Aufrufenden möglich, diese Schalterkombination festzulegen. .PP Wenn ein neuer Namensraum (der kein Benutzernamensraum ist) mittels \fBclone\fP(2) oder \fBunshare\fP(2) erstellt wird, zeichnet der Kernel den Benutzernamensraum des erstellenden Prozesses als Eigentümer des neuen Namensraums auf. (Diese Zuordnung kann nicht geändert werden). Wenn nachfolgend ein Prozess in dem neuen Namensraum eine privilegierte Aktion durchführt, die auf globalen Ressourcen agiert, die durch den Namensraum isoliert werden, dann erfolgen die Berechtigungsprüfungen gemäß 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\-Namensräume regulierte Ressource, zu ändern (\fBsethostname\fP(2)), dann wird der Kernel bestimmen, welchem Benutzernamensraum der UTS\-Namensraum des Prozesses gehört und prüfen, ob der Prozess über die benötigte Capability (\fBCAP_SYS_ADMIN\fP) in diesem Benutzernamensraum verfügt. .PP .\" .\" ============================================================ .\" Die Aktion \fBNS_GET_USERNS\fP \fBioctl\fP(2) kann zum Erkennen des Benutzernamensraums verwandt werden, dem der Nichtbenutzer\-Namensraum gehört; siehe \fBioctl_ns\fP(2). .SS "Benutzer\- und Gruppenkennungabbildungen: uid_map und gid_map" .\" commit 22d917d80e842829d0ca0a561967d728eb1d6303 Wenn ein Benutzernamensraum erstellt wird, beginnt er mit einer Abbildung der Benutzerkennungen (Gruppenkennungen) auf die des Vorgängernamensraumes. Die Dateien \fI/proc/[PID]/uid_map\fP und \fI/proc/[PID]/gid_map\fP (verfügbar seit Linux 3.5) legen diese Abbildungen für die Benutzer\- und Gruppenkennungen innerhalb des Benutzernamensraumes für den Prozess \fIPID\fP offen. Diese Dateien können ausgelesen werden, um die Abbildungen innerhalb eines Benutzernamensraums zu betrachten und (einmal) beschrieben zu werden, um diese Abbildungen zu definieren. .PP Die Beschreibung in den folgenden Absätzen erklärt die Details für \fIuid_map\fP; \fIgid_map\fP ist vollständig identisch, sofern jedes Vorkommen von »Benutzerkennung« durch »Gruppenkennung« ersetzt wird. .PP Die Datei \fIuid_map\fP legt die Abbildung der Benutzerkennung von dem Benutzernamensraum des Prozesses \fIPID\fP in den Benutzernamensraum des Prozesses offen, der \fIuid_map\fP öffnete (siehe aber auch die nachfolgende Qualifizierung dieses Punktes). Mit anderen Worten, Prozesse, die sich in verschiedenen Benutzernamensräumen befinden, werden möglicherweise andere Werte sehen, wenn sie aus einer bestimmten Datei \fIuid_map\fP lesen, abhängig von der Benutzerkennungsabbildung für den Benutzernamensraum des lesenden Prozesses. .PP Jede Zeile der Datei \fIuid_map\fP legt eine 1\-zu\-1\-Abbildung des Bereichs fortlaufender Benutzerkennungen zwischen zwei Benutzernamensräumen 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 Benutzernamensräume an. Die dritte Zahl gibt die Länge des abgebildeten Bereichs an. Im Detail werden die Felder wie folgt interpretiert: .IP (1) 4 Der Anfang des Bereichs von Benutzerkennungen in dem Benutzernamensraum des Prozesses \fIPID\fP. .IP (2) Der Anfang des Bereichs von Benutzerkennungen, auf die die Benutzerkennungen aus Feld eins abgebildet werden. Wie Feld zwei interpretiert wird, hängt davon ab, ob der Prozess, der \fIuid_map\fP öffnete und der Prozess \fIPID\fP sich in dem gleichen Benutzernamensraum befinden, wie folgt: .RS .IP a) 3 Falls sich die zwei Prozesse in verschiedenen Benutzernamensräumen befinden: Feld zwei ist der Anfang des Bereichs von Benutzerkennungen in dem Benutzernamensraum des Prozesses, der \fIuid_map\fP öffnete. .IP b) Falls die zwei Prozesse im gleichen Benutzernamensraum sind: Feld zwei ist der Anfang des Bereichs von Benutzerkennungen in dem Vorgängerbenutzernamensraum des Prozesses \fIPID\fP. Dieser Fall ermöglicht es dem Öffnenden von \fIuid_map\fP (der typische Fall hier ist das Öffnen von \fI/proc/self/uid_map\fP) die Abbildung der Benutzerkennungen in den Benutzernamensraum des Prozesses, der diesen Benutzernamensraum erstellte, zu sehen. .RE .IP (3) Die Länge des Bereichs von Benutzerkennungen, die zwischen den zwei Benutzernamensräumen abgebildet wird. .PP Systemaufrufe, die Benutzerkennungen (Gruppenkennungen) zurückliefern\(embeispielsweise \fBgetuid\fP(2), \fBgetgid\fP(2) und die Berechtigungsdatenfelder in der durch \fBstat\fP(2) zurückgelieferten Struktur\(emliefern die Benutzerkennung (Gruppenkennung) abgebildet auf den Benutzernamensraum des Aufrufenden zurück. .PP Wenn ein Prozess auf eine Datei zugreift, werden seine Benutzer\- und Gruppenkennungen zum Zwecke der Zugriffsprüfung und der Zuweisungen von Kennungen beim Erstellen von Dateien auf die des anfänglichen Benutzernamensraumens abgebildet. Wenn ein Prozess die Dateibenutzer\- und \-gruppenkennungen über \fBstat\fP(2) ermittelt, werden die Kennungen in die andere Richtung abgebildet, um Werte relativ zu den Prozessbenutzer\- und \-gruppenkennungsabildungen zu erstellen. .PP Der anfängliche Benutzernamensraum hat keinen Vorgängernamensraum. Aus Konsistenzgründen stellt der Kernel Pseudo\-Benutzer\- und \-Gruppenkennungsabbildungsdateien für diesen Namensraum bereit. Wird vom anfänglichen Namensraum aus auf die Datei \fIuid_map\fP (\fIgid_map\fP ist identisch) geschaut, ergibt sich: .PP .in +4n .EX $ \fBcat /proc/$$/uid_map\fP 0 0 4294967295 .EE .in .PP .\" .\" ============================================================ .\" 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) Vorgängernamensraum abgebildet ist und die Länge des Bereichs die größte vorzeichenlose 32\-bit\-Ganzzahl ist. Dies lässt 4294967295 (der vorzeichenbehaftete 32\-bit\-Wert) nicht abgebildet. Dies ist absichtlich: \fI(uid_t)\ \-1\fP wird von einer Reihe von Schnittstellen (z.B. \fBsetreuid\fP(2)) dazu verwandt, »keine Benutzerkennung« festzulegen. Da \fI(uid_t)\ \-1\fP nicht abgebildet und unbenutzbar ist, wird sichergestellt, dass es keine Verwirrung bei der Verwendung dieser Schnittstellen gibt. .SS "Definieren von Benutzer\- und Gruppenkennungsabbildungen; Schreiben in uid_map und gid_map" .PP Nach der Erstellung eines neuen Benutzernamensraumes kann die Datei \fIuid_map\fP von \fIeinem\fP der Prozesse in dem Namensraum \fIeinmalig\fP geschrieben werden, um die Abbildung der Benutzerkennungen in dem neuen Benutzernamensraum zu definieren. Jeder Versuch, mehr als einmal in eine Datei \fIuid_map\fP in einem Benutzernamensraum zu schreiben, schlägt mit dem Fehler \fBEPERM\fP fehl. Ähnliche Regeln gelten für Dateien \fIgid_map\fP. .PP Die in \fIuid_map\fP (\fIgid_map\fP) geschriebenen Zeilen müssen die folgenden Regeln erfüllen: .IP * 3 Die drei Felder müssen gültige Zahlen sein und das letzte Feld muss größer als 0 sein. .IP * Zeilen werden durch einen Zeilenumbruch beendet. .IP * .\" 5*12-byte records could fit in a 64B cache line .\" commit 6397fac4915ab3002dc15aae751455da1a852f25 Es gibt eine Beschränkung bezüglich der Anzahl der Zeilen in der Datei. In Linux 4.14 und älter war diese Beschränkung (willkürlich) auf 5 Zeilen gesetzt. Seit Linux 4.15 ist diese Beschränkung 340 Zeilen. Zusätzlich muss die Anzahl an in diese Datei geschriebenen Bytes kleiner als die Seitengröße des Systems sein und das Schreiben muss am Anfang der Datei beginnen (d.h. \fBlseek\fP(2) und \fBpwrite\fP(2) können nicht zum Schreiben an einen von Null verschiedenen Versatz in der Datei verwandt werden). .IP * .\" commit 0bd14b4fd72afd5df41e9fd59f356740f22fceba Die Bereiche der Benutzerkennungen (Gruppenkennungen), die in den einzelnen Zeilen angegeben sind, dürfen sich nicht gegenseitig überlappen. In der anfänglichen Implementierung (Linux 3.8) wurde diese Anforderung durch eine simplistische Implementierung erfüllt, die weitere Einschränkungen auferlegte, dass die Werte sowohl in Feld 1 als auch Feld 2 von aufeinanderfolgenden Zeilen in aufsteigender numerischer Reihenfolge sein mussten, womit andernfalls gültige Abbildungen nicht erstellt werden konnten. Linux 3.9 und neuer korrigierte diese Beschränkung und erlaubte jede Kombination von nichtüberlappenden Abbildungen. .IP * Mindestens eine Zeile muss in die Datei geschrieben werden. .PP Schreibvorgänge, die die obigen Regeln verletzen, schlagen mit dem Fehler \fBEINVAL\fP fehl. .PP Damit ein Prozess in die Datei \fI/proc/[PID]/uid_map\fP (\fI/proc/[PID]/gid_map\fP) schreiben kann, müssen alle der folgenden Anforderungen erfüllt sein: .IP 1. 3 Der schreibende Prozess muss über die Capability \fBCAP_SETUID\fP (\fBCAP_SETGID\fP) des Benutzernamensraums des Prozeses \fIPID\fP verfügen. .IP 2. Der schreibende Prozess muss entweder in dem Benutzernamensraum des Prozesses \fIPID\fP oder in dem Vorgängernamensraum des Prozesses \fIPID\fP sein. .IP 3. Die abgebildeten Benutzerkennungen (Gruppenkennungen) müssen wiederum eine Abbildung in dem Vorgänger\-Benutzernamensraum haben. .IP 4. Einer der folgenden zwei Fälle trifft zu: .RS .IP * 3 \fIEntweder\fP verfügt der schreibende Prozess über die Capability \fBCAP_SETUID\fP (\fBCAP_SETGID\fP) in dem \fIVorgänger\fPnamensraum. .RS .IP + 3 Es gelten keine weiteren Einschränkungen; der Prozess kann Abbildungen auf beliebige Benutzerkennungen (Gruppenkennungen) im Vorgängernamensraum durchführen. .RE .IP * 3 \fIOder\fP es gelten alle der folgenden Beschränkungen: .RS .IP + 3 Die in \fIuid_map\fP (\fIgid_map\fP) geschriebenen Daten müssen aus einer einzelnen Zeile bestehen, die die effektive Benutzerkennung (Gruppenkennung) des schreibenden Prozesses in dem Vorgängernamensraum auf eine Benutzerkennung (Gruppenkennung) in den Benutzernamensraum abbildet. .IP + Der schreibende Prozess muss die gleiche effektive Benutzerkennung wie der Prozess haben, der den Benutzernamensraum erstellte. .IP + Im Falle von \fIgid_map\fP muss zuerst die Verwendung des Systemaufrufs \fBsetgroups\fP(2) verboten werden, indem »\fIdeny\fP« in die Datei \fI/proc/[PID]/setgroups\fP geschrieben wird (siehe unten), bevor in \fIgid_map\fP geschrieben wird. .RE .RE .PP .\" .\" ============================================================ .\" Schreibaktionen, die die obigen Regeln verletzen, werden mit \fBEPERM\fP fehlschlagen. .SS "Wechselwirkung mit Systemaufrufen, die Prozessbenutzerkennungen oder \-gruppenkennungen ändern" In einem Benutzernamensraum, in dem die Datei \fIuid_map\fP noch nicht geschrieben wurde, werden die Systemaufrufe, die die Benutzerkennung ändern, fehlschlagen. Ähnlich werden die Systemaufrufe, die die Gruppenkennungen ändern, fehlschlagen, falls die Datei \fIgid_map\fP noch nicht geschrieben wurde. Nachdem die Dateien \fIuid_map\fP und \fIgid_map\fP geschrieben wurden, können nur die abgebildeten Werte in Systemaufrufen verwandt werden, die die Benutzer\- und Gruppenkennungen ändern. .PP Für Benutzerkennungen sind die relevanten Systemaufrufe unter anderem \fBsetuid\fP(2), \fBsetfsuid\fP(2), \fBsetreuid\fP(2) und \fBsetresuid\fP(2). Für Gruppenkennungen sind die relevanten Systemaufrufe unter anderem \fBsetgid\fP(2), \fBsetfsgid\fP(2), \fBsetregid\fP(2), \fBsetresgid\fP(2) und \fBsetgroups\fP(2). .PP .\" Things changed in Linux 3.19 .\" commit 9cc46516ddf497ea16e8d7cb986ae03a0f6b92f8 .\" commit 66d2f338ee4c449396b6f99f5e75cd18eb6df272 .\" http://lwn.net/Articles/626665/ .\" .\" ============================================================ .\" Durch Schreiben von »\fIdeny\fP« in die Datei \fI/proc/[PID]/setgroups\fP vor dem Schreiben von \fI/proc/[PID]/gid_map\fP wird \fBsetgroups\fP(2) in einem Benutzernamensraum dauerhaft deaktiviert und erlaubt Schreiben von \fI/proc/[PID]/gid_map\fP, ohne über die Capability \fBCAP_SETGID\fP im Vorgängernamensraum zu verfügen. .SS "Die Datei \fI/proc/[PID]/setgroups\fP" .\" .\" commit 9cc46516ddf497ea16e8d7cb986ae03a0f6b92f8 .\" commit 66d2f338ee4c449396b6f99f5e75cd18eb6df272 .\" http://lwn.net/Articles/626665/ .\" http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2014-8989 .\" Die Datei \fI/proc/[PID]/setgroups\fP zeigt die Zeichenkette »\fIallow\fP«, falls Prozesse in dem Benutzernamensraum, der den Prozess \fIPID\fP enthält, die Erlaubnis haben, den Systemaufruf \fBsetgroups\fP(2) einzusetzen. Sie zeigt »\fIdeny\fP« an, falls \fBsetgroups\fP(2) in diesem Benutzernamensraum nicht erlaubt ist. Beachten Sie, dass Aufrufe von \fBsetgroups\fP(2) auch nicht erlaubt sind, falls \fI/proc/[PID]/gid_map\fP noch nicht gesetzt wurde, unabhängig von dem Wert der Datei \fI/proc/[PID]/setgroups\fP (und unabhängig von den Capabilitys des Prozesses). .PP Ein privilegierter Prozess (einer mit der Capability \fBCAP_SYS_ADMIN\fP in dem Namensraum) darf eine der Zeichenketten »\fIallow\fP« oder »\fIdeny\fP« in diese Datei schreiben, \fIbevor\fP eine Gruppenkennungsabbildung für diesen Benutzernamensraum in die Datei \fI/proc/[PID]/gid_map\fP geschrieben wird. Durch Schreiben der Zeichenkette »\fIdeny\fP« wird jedem Prozess in diesem Benutzernamensraum der Einsatz von \fBsetgroups\fP(2) verboten. .PP Die Essenz der in den vorhergehenden Absätzen beschriebenen Beschränkungen ist, dass das Schreiben in \fI/proc/[PID]/setgroups\fP nur so lange erlaubt ist, wie \fBsetgroups\fP(2) nicht erlaubt ist, da \fI/proc/[PID]/gid_map\fP noch nicht gesetzt wurde. Damit wird sichergestellt, dass ein Prozess nicht von einem Zustand, bei dem \fBsetgroups\fP(2) erlaubt ist, zu einem Zustand, bei dem \fBsetgroups\fP(2) verboten ist, übergehen kann; ein Prozess kann nur von \fBsetgroups\fP(2) nicht erlaubt zu \fBsetgroups\fP(2) erlaubt übergehen. .PP Der Vorgabewert für diese Datei in dem anfänglichen Namensraum ist »\fIallow\fP«. .PP Sobald \fI/proc/[PID]/gid_map\fP geschrieben wurde (wodurch \fBsetgroups\fP(2) in dem Benutzernamensraum aktiviert wird), ist es nicht mehr möglich, \fBsetgroups\fP(2) durch Schreiben von »\fIdeny\fP« in \fI/proc/[PID]/setgroups\fP zu verbieten (das Schreiben schlägt mit \fBEPERM\fP fehl). .PP Ein Nachfolgernamensraum erbt die Einstellungen \fI/proc/[PID]/setgroups\fP von seinem Vorgänger. .PP Falls die Datei \fIsetgroups\fP den Wert »\fIdeny\fP« enthält, dann kann der Systemaufruf \fBsetgroups\fP(2) in diesem Namensraum nachfolgend nicht mehr aktiviert werden (durch Schreiben von »\fIallow\fP« in die Datei). (Versuche, dies durchzuführen, schlagen mit \fBEPERM\fP fehl.) Diese Beschränkung wird auch an alle Nachfolgerbenutzernamensräume dieses Benutzernamensraums weitergeleitet. .PP .\" .\" /proc/PID/setgroups .\" [allow == setgroups() is allowed, "deny" == setgroups() is disallowed] .\" * Can write if have CAP_SYS_ADMIN in NS .\" * Must write BEFORE writing to /proc/PID/gid_map .\" .\" setgroups() .\" * Must already have written to gid_map .\" * /proc/PID/setgroups must be "allow" .\" .\" /proc/PID/gid_map -- writing .\" * Must already have written "deny" to /proc/PID/setgroups .\" .\" ============================================================ .\" Die Datei \fI/proc/[PID]/setgroups\fP wurde in Linux 3.19 hinzugefügt; allerdings wurde sie auch auf viele frühere stabile Kernel rückportiert, 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 \fBsetgroups\fP(2) einem Prozess Dateizugriff erlauben könnte, den er vorher nicht hatte. Vor der Existenz von Benutzernamensräumen führte dies zu keine Sorgen, da nur ein privilegierter Prozess (einer mit der Capability \fBCAP_SETGID\fP) \fBsetgroups\fP(2) aufrufen konnte. Mit der Einführung von Benutzernamensräumen wurde es für einen nicht privilegierten Prozess allerdings möglich, einen neuen Namensraum zu erstellen, in dem der Benutzer alle Privilegien hatte. Dies ermöglichte es dann vorher nicht privilegierten Benutzern Gruppen abzugeben und damit Dateizugriff zu erlangen, den sie vorher nicht hatten. Die Datei \fI/proc/[PID]/setgroups\fP wurde hinzugefügt, um dieses Sicherheitsproblem zu adressieren, indem jeder Pfad für einen nicht privilegierten Prozess, Gruppen mit \fBsetgroups\fP(2) abzugeben, verboten wurde. .SS "Nicht abgebildete Benutzer\- und Gruppenkennungen" .PP .\" from_kuid_munged(), from_kgid_munged() Es gibt verschiedene Stellen, an denen nicht abgebildete Benutzerkennungen (Gruppenkennungen) im Anwendungsraum offengelegt werden können. Beispielsweise könnte der erste Prozess in einem neuen Benutzernamensraum \fBgetuid\fP(2) aufrufen, bevor eine Benutzerkennungsabbildung für den Namensraum definiert wurde. In den meisten solcher Fälle wird eine nicht abgebildete Benutzerkennung in die Überlauf\-Benutzerkennung (Gruppenkennung) konvertiert; der Vorgabewert für die Überlauf\-Benutzerkennung (Gruppenkennung) ist 65534. Siehe die Beschreibung von \fI/proc/sys/kernel/overflowuid\fP und \fI/proc/sys/kernel/overflowgid\fP in \fBproc\fP(5). .PP .\" also SO_PEERCRED Zu den Fällen, in denen nicht abgebildete Benutzerkennungen auf diese Art abgebildet werden, gehören Systemaufrufe, die Benutzerkennungen zurückliefern (\fBgetuid\fP(2), \fBgetgid\fP(2) und ähnliche), Benutzerberechtigungen, die über ein UNIX\-Domain\-Socket übergeben werden, Benutzerberechtigungen, die von \fBstat\fP(2), \fBwaitid\fP(2) und den System\-V\-IPC\-»ctl«\-\fBIPC_STAT\fP\-Aktionen zurückgeliefert werden, Benutzerberechtigungen, die mittels \fI/proc/[PID]/status\fP und den Dateien in \fI/proc/sysvipc/*\fP offengelegt werden, Benutzerberechtigungen, die über das Feld \fIsi_uid\fP in dem mit einem Signal \fIsiginfo_t\fP empfangenen Feld zurückgeliefert werden (siehe \fBsigaction\fP(2)), Benutzerberechtigungen, die in die Prozessbuchhaltungsdatei geschrieben werden (siehe \fBacct\fP(5)) und Benutzerberechtigungen, die mit POSIX\-Nachrichtenwarteschlangen\-Benachrichtigungen zurückgeliefert werden (siehe \fBmq_notify\fP(3)). .PP .\" from_kuid(), from_kgid() .\" Also F_GETOWNER_UIDS is an exception .\" .\" ============================================================ .\" Es gibt einen erwähnenswerten Fall, bei dem nicht abgebildete Benutzer\- und Gruppenkennungen \fInicht\fP in die entsprechende Überlaufkennung konvertiert werden. Beim Betrachten einer Datei \fIuid_map\fP oder \fIgid_map\fP, bei der es keine Abbildung für das zweite Feld gibt, wird das Feld als 4294967295 (\-1 als eine vorzeichenlose Ganzzahl) dargestellt. .SS Dateizugriff .PP .\" .\" ============================================================ .\" Um Berechtigungen zu bestimmen, wenn ein nicht privilegierter Prozess auf eine Datei zugreift, werden die Prozessberechtigungen (UID, GID) und die Dateiberechtigungen letztendlich auf die zurückabgebildet, die sie im anfänglichen Benutzernamensraum wären und dann verglichen, um die Berechtigungen zu bestimmen, die der Prozess auf die Datei hat. Das gleiche trifft auch für andere Objekte zu, die das Zugriffsmodell mit Benutzerberechtigungen sowie Berechtigungsmasken einsetzen, wie System\-V\-IPC\-Objekte. .SS "Aktionen mit Datei\-bezogenen Capabilitys" .PP Bestimmte Capabilitys erlauben es einem Prozess, verschiedene, durch den Kernel durchgesetzte Beschränkungen zu umgehen, wenn Aktionen auf Dateien durchgeführt werden, die anderen Benutzern oder Gruppen gehören. Diese Capabilitys sind \fBCAP_CHOWN\fP, \fBCAP_DAC_OVERRIDE\fP, \fBCAP_DAC_READ_SEARCH\fP, \fBCAP_FOWNER\fP und \fBCAP_FSETID\fP. .PP Innerhalb eines Benutzernamensraumes erlauben diese Capabilitys einem Prozess, die Regeln zu umgehen, falls der Prozess über die relevante Capability über die Datei verfügt. Das bedeutet: .IP * 3 Der Prozess hat die relevante effektive Capability in seinem eigenen Benutzernamensraum; und .IP * die Benutzer\- und Gruppenkennung der Datei habe beide gültige Abbildungen in dem Benutzernamensraum. .PP .\" These are the checks performed by the kernel function .\" inode_owner_or_capable(). There is one exception to the exception: .\" overriding the directory sticky permission bit requires that .\" the file has a valid mapping for both its UID and GID. .\" .\" ============================================================ .\" Die Capability \fBCAP_FOWNER\fP wird etwas besonders behandelt: sie erlaubt einem Prozess, die entsprechenden Regeln zu umgehen, solange zumindest die Benutzerkennung der Datei über eine Abbildung in dem Benutzernamensraum verfügt (d.h. die Gruppenkennung der Datei benötigt keine gültige Abbildung). .SS "Set\-user\-ID\- und set\-group\-ID\-Programme" .PP .\" .\" ============================================================ .\" Wenn ein Prozess innerhalb eines Benutzernamensraums ein set\-user\-ID\- (set\-group\-ID)\-Programm ausführt, wird die effektive Benutzer\- (Gruppen\-)Kennung des Prozesses innerhalb des Namensraums auf denjenigen Wert geändert, der für die Benutzer\- (Gruppen)kennung der Datei abgebildet ist. Falls allerdings entweder die Benutzer\- \fIoder\fP die Gruppenkennung der Datei über keine Abbildung innerhalb des Namensraums verfügt, wird das set\-user\-ID\- (set\-group\-ID\-)Bit ohne Rückmeldung ignoriert: das neue Programm wird ausgeführt, aber die effektive Benutzer\- (Gruppen\-)Kennung des Prozesses bleibt unverändert. (Dies spiegelt die Semantik bei der Ausführung eines set\-user\-ID\- oder set\-group\-ID\-Programmes wider, das sich auf einem Dateisystem befindet, das mit dem Schalter \fBMS_NOSUID\fP eingehängt wurde, wie dies in \fBmount\fP(2) beschrieben ist.) .SS Verschiedenes .PP .\" Wenn die Benutzer\- und Gruppenkennungen eines Prozesses über ein UNIX\-Domain\-Socket an einen Prozess in einem anderen Benutzernamensraum übergeben werden (siehe die Beschreibung von \fBSCM_CREDENTIALS\fP in \fBunix\fP(7)), werden sie in die entsprechenden Werte der Benutzer\- und Gruppenkennungsabbildungen des empfangenen Prozesses übersetzt. .SH "KONFORM ZU" .\" Namensräume sind eine Linux\-spezifische Funktionalität. .SH ANMERKUNGEN .\" .\" ============================================================ .\" Über die Jahre wurden eine Reihe von Funktionalitäten zu dem Linux\-Kernel hinzugefügt, die nur privilegierten Benutzern verfügbar gemacht wurden, da sie möglicherweise set\-user\-ID\-root\-Anwendungen durcheinander bringen könnten. Im Allgemeinen wird es sicher, einem Root\-Benutzer in einem Benutzernamensraum die Verwendung dieser Funktionalitäten zu erlauben, da es unmöglich ist, mehr Privilegien zu erlangen, als der Root\-Benutzer innerhalb eines Benutzernamensraumes hat, während der Prozess im Benutzernamensraum ist. .SS Verfügbarkeit Die Verwendung von Benutzernamensräumen benötigt einen Kernel, der mit der Option \fBCONFIG_USER_NS\fP konfiguriert ist. Benutzernamensräume benötigen die Unterstützung in einer ganzen Reihe von Subsystemen im Kernel. Wird ein nicht unterstütztes Subsystem in den Kernel konfiguriert, dann ist es nicht möglich, die Unterstützung von Benutzernamensräumen zu konfigurieren. .PP .\" commit d6970d4b726cea6d7a9bc4120814f95c09571fc3 .\" Seit Linux 3.8 unterstützen die wichtigsten Subsysteme Benutzernamensräume, aber eine Reihe von Dateisystemen hatten noch nicht die benötigte Infrastruktur, um Benutzer\- und Gruppenkennungen zwischen Benutzernamensräumen abzubilden. Linux 3.9 fügte die benötigte Infrastruktur für viele der verbliebenen, nicht unterstützten Dateisysteme (Plan 9 (9P), Andrew File System (AFS), Ceph, CIFS, CODA, NFS und OCFS2) hinzu. Linux 3.12 fügte Unterstützung für das letzte große verbliebene und nicht unterstützte Dateisystem hinzu: XFS. .SH BEISPIELE Das nachfolgende Programm ist zum Experimentieren mit Benutzernamensräumen sowie anderen Arten von Namensräumen gedacht. Es erstellt einen Namensraum, wie er über die Befehlszeilenoptionen angegeben ist, und führt dann innerhalb dieser Namensräume einen Befehl aus. Die Kommentare und die Funktion \fIusage\fP() innerhalb des Programmes bieten eine vollständige Erklärung des Programms. Die nachfolgende Shell\-Sitzung zeigt seine Verwendung. .PP Zuerst schauen wir auf die Laufzeitumgebung: .PP .in +4n .EX $ \fBuname \-rs\fP # Benötigt Linux 3.8 oder neuer Linux 3.8.0 $ \fBid \-u\fP # Ausführung als nicht privilegierter Benutzer 1000 $ \fBid \-g\fP 1000 .EE .in .PP Jetzt wird eine neue Shell in neuen Benutzer\- (\fI\-U\fP), Einhänge\- (\fI\-m\fP) und PID\- (\fI\-p\fP) Namensräumen gestartet, wobei innerhalb des Benutzernamensraums die Benutzerkennung (\fI\-M\fP) und Gruppenkennung (\fI\-G\fP) 1000 auf 0 abgebildet wird: .PP .in +4n .EX $ \fB./userns_child_exec \-p \-m \-U \-M \(aq0 1000 1\(aq \-G \(aq0 1000 1\(aq bash\fP .EE .in .PP Diese Shell hat PID 1, da sie der erste Prozess in dem neuen PID\-Namensraum ist: .PP .in +4n .EX bash$ \fBecho $$\fP 1 .EE .in .PP Wird ein neues Dateisystem \fI/proc\fP eingehängt und alle in dem neuen PID\-Namensraum sichtbaren Prozesse aufgelistet, kann gesehen werden, dass die Shell keinerlei Prozesse außerhalb des PID\-Namensraumes sehen kann: .PP .in +4n .EX bash$ \fBmount \-t proc proc /proc\fP bash$ \fBps ax\fP PID TTY STAT TIME COMMAND 1 pts/3 S 0:00 bash 22 pts/3 R+ 0:00 ps ax .EE .in .PP Innerhalb des Benutzernamensraumes hat die Shell die Benutzer\- und Gruppenkennung 0 und eine vollständige Menge an erlaubten und effektiven Capabilitys: .PP .in +4n .EX bash$ \fBcat /proc/$$/status | egrep \(aq\(ha[UG]id\(aq\fP Uid: 0 0 0 0 Gid: 0 0 0 0 bash$ \fBcat /proc/$$/status | egrep \(aq\(haCap(Prm|Inh|Eff)\(aq\fP CapInh: 0000000000000000 CapPrm: 0000001fffffffff CapEff: 0000001fffffffff .EE .in .SS Programmquelltext \& .EX /* 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 Namensräumen ausführt; 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 /* Eine einfache Fehlerbehandlungsfunktion; gibt basierend auf dem Wert in »errno« eine Fehlermeldung aus und beendet den aufrufenden Prozess*/ #define errExit(Nachricht) do { perror(Nachricht); exit(EXIT_FAILURE); \e } while (0) struct child_args { char **argv; /* Vom Kind auszuführender 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…]\en\en", pname); fprintf(stderr, "Erstellt einen Kindprozess, der einen Shellbefehl " "in einem neuen Benutzernamensraum ausführt\en" "und möglicherweise auch anderen neuen Namensräumen.\en\en"); fprintf(stderr, "Optionen können sein:\en\en"); #define fpe(str) fprintf(stderr, " %s", str); fpe("\-i Neuer IPC\-Namensraum\en"); fpe("\-m Neuer Einhänge\-Namensraum\en"); fpe("\-n Neuer Netzwerk\-Namensraum\en"); fpe("\-p Neuer PID\-Namensraum\en"); fpe("\-u Neuer UTS\-Namensraum\en"); fpe("\-U Neuer Benutzernamensraum\en"); fpe("\-M uid_map Angabe einer UID\-Abbildung für Benutzernamensraum\en"); fpe("\-G gid_map Angabe einer GID\-Abbildung für Benutzernamensraum\en"); fpe("\-z Benutzer\-UID und \-GID auf 0 im Benutzernamensraum abbilden\en"); fpe(" (äquivalent zu: \-M \(aq0 1\(aq \-G \(aq0 1\(aq)\en"); fpe("\-v Anzeige ausführlicher Meldungen\en"); fpe("\en"); fpe("Falls \-z, \-M oder \-G angegeben wird, ist \-U verpflichtend.\en"); fpe("Es ist nicht erlaubt, sowohl \-z als auch entweder \-M oder \-G anzugeben.\en"); fpe("\en"); fpe("Abbildungszeichenketten für \-M und \-G bestehen aus Datensätzen der folgenden Form:\en"); fpe("\en"); fpe(" Namensrauminterne\-Kennung Namensraumexterne\-Kennung Länge\en"); fpe("\en"); fpe("Eine Abbildungszeichenkette kann mehrere Datensätze enthalten," " getrennt durch Kommata;\en"); fpe("die Kommata werden vor dem Schreiben in die Abbildungsdateien durch" " Zeilenumbrüche ersetzt.\en"); exit(EXIT_FAILURE); } /* Aktualisiert die Abbildungsdatei »Datei« mit dem in »Abbildung« bereitgestellten Wert, einer Zeichenkette, die eine UID\- oder GID\- Abbildung definiert. Eine UID\- oder GID\-Abbildung besteht aus einem oder mehreren, durch Zeilenumbrüche getrennten Datensätzen der folgenden Form: Namensrauminterne\-Kennung Namensraumexterne\-Kennung Länge Für die Befehlszeile zu verlangen, dass Zeichenketten mit Zeilenumbrüchen bereitgestellt werden, ist natürlich unbequem. Daher erlauben wir die Verwendung von Kommata zur Begrenzung von Datensätzen in dieser Zeichenkette und ersetzen sie vor dem Schreiben in die Datei durch Zeilenumbrüche. */ static void update_map(char *mapping, char *map_file) { int fd; size_t map_len; /* Länge der »Abbildung« */ /* Kommata durch Zeilenumbrüche in Abbildungszeichenkette ersetzen. */ map_len = strlen(mapping); for (int j = 0; j < map_len; j++) if (mapping[j] == \(aq,\(aq) mapping[j] = \(aq\en\(aq; fd = open(map_file, O_RDWR); if (fd == \-1) { fprintf(stderr, "FEHLER: open %s: %s\en", map_file, strerror(errno)); exit(EXIT_FAILURE); } if (write(fd, mapping, map_len) != map_len) { fprintf(stderr, "FEHLER: write %s: %s\en", map_file, strerror(errno)); exit(EXIT_FAILURE); } close(fd); } /* Linux 3.19 änderte 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 abzugeben. Das Fazit der 3.19er Änderung ist, dass die Verwendung des Systemaufrufs setgroups() in diesem Benutzernamensraum zuerst durch Schreiben von »deny« in eine der Dateien /proc/PID/setgroups für 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 unterstützt. Dann wird diese Datei nicht existieren und das System wird nicht die Beschränkungen erzwingen, die Linux 3.19 hinzugefügt 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\en", setgroups_path, strerror(errno)); return; } if (write(fd, str, strlen(str)) == \-1) fprintf(stderr, "FEHLER: write %s: %s\en", setgroups_path, strerror(errno)); close(fd); } static int /* Funktion für 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 für das Ende des Schreibens schließen, so dass wir EOF sehen, wenn der Elternprozess seinen Deskriptor schließt. */ if (read(args\->pipe_fd[0], &ch, 1) != 0) { fprintf(stderr, "Fehler im Kind: Lesen von der Pipe lieferte != 0\en"); exit(EXIT_FAILURE); } close(args\->pipe_fd[0]); /* Einen Shell\-Befehl ausführen. */ printf("Gleich wird exec %s ausgeführt\en", args\->argv[0]); execvp(args\->argv[0], args\->argv); errExit("execvp"); } #define STACK_SIZE (1024 * 1024) static char child_stack[STACK_SIZE]; /* Platz für 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 anfängliche »+«\-Zeichen in dem abschließenden getopt()\-Argument verhindert GNU\-artige Vertauschungen der Befehlszeilenoptionen. Das ist nützlich, da manchmal der von diesem Programm selbst ausgeführte »Befehl« über Befehlszeilenoptionen verfügt. Wir wollen nicht, dass getopt() solche als Optionen für 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 \(aqi\(aq: flags |= CLONE_NEWIPC; break; case \(aqm\(aq: flags |= CLONE_NEWNS; break; case \(aqn\(aq: flags |= CLONE_NEWNET; break; case \(aqp\(aq: flags |= CLONE_NEWPID; break; case \(aqu\(aq: flags |= CLONE_NEWUTS; break; case \(aqv\(aq: verbose = 1; break; case \(aqz\(aq: map_zero = 1; break; case \(aqM\(aq: uid_map = optarg; break; case \(aqG\(aq: gid_map = optarg; break; case \(aqU\(aq: 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 während des execve() erhält, wenn der typische Fall vorliegt, dass wir möchten, dass die effektive Benutzerkennung des Kindprozesses auf 0 in dem neuen Benutzernamensraum abgebildet wird. Ohne diese Synchronisation würde der Kindprozess seine Capabilitys verlieren, falls es ein execve() mit einer von Null verschiedenen Benutzerkennung durchführen würde (siehe die Handbuchseite capabilities(7) für Details des Übergangs der Capabilitys eines Prozesses während execve()). */ if (pipe(args.pipe_fd) == \-1) errExit("pipe"); /* Den Kindprozess in dem oder den neuen Namensraum/\-räumen erstellen. */ child_pid = clone(childFunc, child_stack + STACK_SIZE, flags | SIGCHLD, &args); if (child_pid == \-1) errExit("clone"); /* Elternprozess fällt bis hierher durch */ if (verbose) printf("%s: PID des durch clone() erstellten Kindprozesses lautet %jd\en", 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 schließen, 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 */ errExit("waitpid"); if (verbose) printf("%s: beende\en", argv[0]); exit(EXIT_SUCCESS); } .EE .SH "SIEHE AUCH" .\" From the shadow package .\" From the shadow package .\" From the shadow package .\" From the shadow package \fBnewgidmap\fP(1), \fBnewuidmap\fP(1), \fBclone\fP(2), \fBptrace\fP(2), \fBsetns\fP(2), \fBunshare\fP(2), \fBproc\fP(5), \fBsubgid\fP(5), \fBsubuid\fP(5), \fBcapabilities\fP(7), \fBcgroup_namespaces\fP(7), \fBcredentials\fP(7), \fBnamespaces\fP(7), \fBpid_namespaces\fP(7) .PP Die Kernelquelldatei \fIDocumentation/namespaces/resource\-control.txt\fP. .SH KOLOPHON Diese Seite ist Teil der Veröffentlichung 5.10 des Projekts Linux\-\fIman\-pages\fP. Eine Beschreibung des Projekts, Informationen, wie Fehler gemeldet werden können, sowie die aktuelle Version dieser Seite finden sich unter \%https://www.kernel.org/doc/man\-pages/. .PP .SH ÜBERSETZUNG Die deutsche Übersetzung dieser Handbuchseite wurde von Helge Kreutzmann erstellt. .PP Diese Übersetzung ist Freie Dokumentation; lesen Sie die .UR https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License Version 3 .UE oder neuer bezüglich der Copyright-Bedingungen. Es wird KEINE HAFTUNG übernommen. .PP Wenn Sie Fehler in der Übersetzung dieser Handbuchseite finden, schicken Sie bitte eine E-Mail an die .MT debian-l10n-german@lists.debian.org Mailingliste der Übersetzer .ME .