]> git.ipfire.org Git - thirdparty/man-pages.git/commitdiff
namespaces.7: Document the NS_GET_USERNS and NS_GET_PARENT ioctl() operations
authorMichael Kerrisk <mtk.manpages@gmail.com>
Sun, 11 Dec 2016 11:59:04 +0000 (12:59 +0100)
committerMichael Kerrisk <mtk.manpages@gmail.com>
Mon, 12 Dec 2016 06:27:23 +0000 (07:27 +0100)
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
man7/namespaces.7

index 39ddef238dbb56310e6cd616c4d43357705abe18..47832321a1b4280a9895bc9df1f39405f1a0636b 100644 (file)
@@ -323,11 +323,255 @@ and
 Use of UTS namespaces requires a kernel that is configured with the
 .B CONFIG_UTS_NS
 option.
+.\"
+.\" ============================================================
+.\"
+.SS Introspecting namespace relationships
+Since Linux 4.9,
+.\" commit bcac25a58bfc6bd79191ac5d7afb49bea96da8c9
+.\" commit 6786741dbf99e44fb0c0ed85a37582b8a26f1c3b
+.\" commit a7306ed8d94af729ecef8b6e37506a1c6fc14788
+.\" commit 6ad92bf63e45f97e306da48cd1cbce6e4fef1e5d
+two
+.BR ioctl (2)
+operations are provided to allow introspection of namespace relationships
+(see
+.BR user_namespaces (7)
+and
+.BR pid_namespaces (7)).
+The form of the calls is:
+
+    ioctl(fd, request);
+
+In each case,
+.I fd
+refers to a
+.IR /proc/[pid]/ns/*
+file.
+.TP
+.BR NS_GET_USERNS
+Returns a file descriptor that refers to the owning user namespace
+for the namespace referred to by
+.IR fd .
+.TP
+.BR NS_GET_PARENT
+Returns a file descriptor that refers to the parent namespace of
+the namespace referred to by
+.IR fd .
+This operation is valid only for hierarchical namespaces
+(i.e., PID and user namespaces).
+For user namespaces,
+.BR NS_GET_PARENT
+is synonymous with
+.BR NS_GET_USERNS .
+.PP
+In each case, the returned file descriptor is opened with
+.BR O_RDONLY
+and
+.BR O_CLOEXEC
+(close-on-exec).
+.PP
+By applying
+.BR fstat (2)
+to the returned file descriptor, one obtains a
+.I stat
+structure whose
+.I st_ino
+(inode number) field identifies the owning/parent namespace.
+This inode number can be matched with the inode number of another
+.IR /proc/[pid]/ns/{pid,user}
+file to determine whether that is the owning/parent namespace.
+
+Either of these
+.BR ioctl (2)
+operations can fail with the following error:
+.TP
+.B EPERM
+The requested namespace is outside of the caller's namespace scope.
+This error can occur if, for example, the owning user namespace is an
+ancestor of the caller's current user namespace.
+It can also occur on attempts to obtain the parent of the initial
+user or PID namespace.
+.PP
+Additionally, the
+.B NS_GET_PARENT
+operation can fail with the following error:
+.TP
+.B EINVAL
+.I fd
+refers to a nonhierarchical namespace.
+.PP
+See the EXAMPLE section for an example of the use of these operations.
 .SH CONFORMING TO
 Namespaces are a Linux-specific feature.
 .SH EXAMPLE
-See
+For one example,
 .BR user_namespaces (7).
+
+The example shown below uses the
+.BR ioctl (2)
+operations described above to perform simple
+introspection of namespace relationships.
+The following shell sessions show various examples of the use
+of this program.
+
+Trying to get the parent of the initial user namespace fails,
+for the reasons explained earlier:
+
+.nf
+.in +4n
+$ \fB./ns_introspect /proc/self/ns/user p\fP
+The parent namespace is outside your namespace scope
+.in
+.fi
+
+Create a process running
+.BR sleep (1)
+that resides in new user and UTS namespaces,
+and show that new UTS namespace is associated with the new user namespace:
+
+.nf
+.in +4n
+$ \fBunshare \-Uu sleep 1000 &\fP
+[1] 23235
+$ \fB./ns_introspect /proc/23235/ns/uts\fP
+Inode number of owning user namespace is: 4026532448
+$ \fBreadlink /proc/23235/ns/user \fP
+user:[4026532448]
+.in
+.fi
+
+Then show that the parent of the new user namespace in the preceding
+example is the initial user namespace:
+
+.nf
+.in +4n
+$ \fBreadlink /proc/self/ns/user\fP
+user:[4026531837]
+$ \fB./ns_introspect /proc/23235/ns/user\fP
+Inode number of owning user namespace is: 4026531837
+.in
+.fi
+
+Start a shell in a new user namespace, and show that from within
+this shell, the parent user namespace can't be discovered.
+Similarly, the UTS namespace
+(which is associated with the initial user namespace)
+can't be discovered.
+
+.nf
+.in +4n
+$ PS1="sh2$ " unshare \-U bash
+sh2$ \fB./ns_introspect /proc/self/ns/user p\fP
+The parent namespace is outside your namespace scope
+sh2$ \fB./ns_introspect /proc/self/ns/uts u\fP
+The owning user namespace is outside your namespace scope
+.in
+.fi
+.SS Program source
+\&
+.nf
+/* ns_introspect.c
+
+   Licensed under GNU General Public License v2 or later
+*/
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <string.h>
+#include <errno.h>
+
+#ifndef NS_GET_USERNS
+#define NSIO    0xb7
+#define NS_GET_USERNS   _IO(NSIO, 0x1)
+#define NS_GET_PARENT   _IO(NSIO, 0x2)
+#endif
+
+int
+main(int argc, char *argv[])
+{
+    int fd, userns_fd, parent_fd;
+    struct stat sb;
+
+    if (argc < 2) {
+        fprintf(stderr, "Usage: %s /proc/[pid]/ns/[file] [p|u]\\n",
+                argv[0]);
+        fprintf(stderr, "\\nDisplay the result of one or both "
+                "of NS_GET_USERNS (u) or NS_GET_PARENT (p)\\n"
+                "for the specified /proc/[pid]/ns/[file]. If neither "
+                "\(aqp\(aq nor \(aqu\(aq is specified,\\n"
+                "NS_GET_USERNS is the default.\\n");
+        exit(EXIT_FAILURE);
+    }
+
+    /* Obtain a file descriptor for the \(aqns\(aq file specified
+       in argv[1] */
+
+    fd = open(argv[1], O_RDONLY);
+    if (fd == \-1) {
+        perror("open");
+        exit(EXIT_FAILURE);
+    }
+
+    /* Obtain a file descriptor for the owning user namespace and
+       then obtain and display the inode number of that namespace */
+
+    if (argc < 3 || strchr(argv[2], \(aqu\(aq)) {
+        userns_fd = ioctl(fd, NS_GET_USERNS);
+
+        if (userns_fd == \-1) {
+            if (errno == EPERM)
+                printf("The owning user namespace is outside "
+                        "your namespace scope\\n");
+            else
+               perror("ioctl\-NS_GET_USERNS");
+            exit(EXIT_FAILURE);
+         }
+
+        if (fstat(userns_fd, &sb) == \-1) {
+            perror("fstat\-userns");
+            exit(EXIT_FAILURE);
+        }
+        printf("Inode number of owning user namespace is: %ld\\n",
+                (long) sb.st_ino);
+
+        close(userns_fd);
+    }
+
+    /* Obtain a file descriptor for the parent namespace and
+       then obtain and display the inode number of that namespace */
+
+    if (argc > 2 && strchr(argv[2], \(aqp\(aq)) {
+        parent_fd = ioctl(fd, NS_GET_PARENT);
+
+        if (parent_fd == \-1) {
+            if (errno == EINVAL)
+                printf("Can\(aq get parent namespace of a "
+                        "nonhierarchical namespace\\n");
+            else if (errno == EPERM)
+                printf("The parent namespace is outside "
+                        "your namespace scope\\n");
+            else
+                perror("ioctl\-NS_GET_PARENT");
+            exit(EXIT_FAILURE);
+        }
+
+        if (fstat(parent_fd, &sb) == \-1) {
+            perror("fstat\-parentns");
+            exit(EXIT_FAILURE);
+        }
+        printf("Inode number of parent namespace is: %ld\\n",
+                (long) sb.st_ino);
+
+        close(parent_fd);
+    }
+
+    exit(EXIT_SUCCESS);
+}
+.fi
 .SH SEE ALSO
 .BR nsenter (1),
 .BR readlink (1),