diff options
Diffstat (limited to 'man2/ioctl_ns.2')
-rw-r--r-- | man2/ioctl_ns.2 | 342 |
1 files changed, 342 insertions, 0 deletions
diff --git a/man2/ioctl_ns.2 b/man2/ioctl_ns.2 new file mode 100644 index 0000000..a11e54b --- /dev/null +++ b/man2/ioctl_ns.2 @@ -0,0 +1,342 @@ +.\" Copyright (c) 2017 by Michael Kerrisk <mtk.manpages@gmail.com> +.\" +.\" SPDX-License-Identifier: Linux-man-pages-copyleft +.\" +.\" +.TH ioctl_ns 2 2023-05-03 "Linux man-pages 6.05.01" +.SH NAME +ioctl_ns \- ioctl() operations for Linux namespaces +.SH DESCRIPTION +.\" ============================================================ +.\" +.SS Discovering namespace relationships +The following +.BR ioctl (2) +operations are provided to allow discovery of namespace relationships (see +.BR user_namespaces (7) +and +.BR pid_namespaces (7)). +The form of the calls is: +.PP +.in +4n +.EX +new_fd = ioctl(fd, request); +.EE +.in +.PP +In each case, +.I fd +refers to a +.IR /proc/ pid /ns/* +file. +Both operations return a new file descriptor on success. +.TP +.BR NS_GET_USERNS " (since Linux 4.9)" +.\" commit bcac25a58bfc6bd79191ac5d7afb49bea96da8c9 +.\" commit 6786741dbf99e44fb0c0ed85a37582b8a26f1c3b +Returns a file descriptor that refers to the owning user namespace +for the namespace referred to by +.IR fd . +.TP +.BR NS_GET_PARENT " (since Linux 4.9)" +.\" commit a7306ed8d94af729ecef8b6e37506a1c6fc14788 +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, +.B NS_GET_PARENT +is synonymous with +.BR NS_GET_USERNS . +.PP +The new file descriptor returned by these operations is opened with the +.B O_RDONLY +and +.B O_CLOEXEC +(close-on-exec; see +.BR fcntl (2)) +flags. +.PP +By applying +.BR fstat (2) +to the returned file descriptor, one obtains a +.I stat +structure whose +.I st_dev +(resident device) and +.I st_ino +(inode number) fields together identify 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. +.PP +Either of these +.BR ioctl (2) +operations can fail with the following errors: +.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. +.TP +.B ENOTTY +The operation is not supported by this kernel version. +.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 EXAMPLES section for an example of the use of these operations. +.\" ============================================================ +.\" +.SS Discovering the namespace type +The +.B NS_GET_NSTYPE +.\" commit e5ff5ce6e20ee22511398bb31fb912466cf82a36 +operation (available since Linux 4.11) can be used to discover +the type of namespace referred to by the file descriptor +.IR fd : +.PP +.in +4n +.EX +nstype = ioctl(fd, NS_GET_NSTYPE); +.EE +.in +.PP +.I fd +refers to a +.IR /proc/ pid /ns/* +file. +.PP +The return value is one of the +.B CLONE_NEW* +values that can be specified to +.BR clone (2) +or +.BR unshare (2) +in order to create a namespace. +.\" ============================================================ +.\" +.SS Discovering the owner of a user namespace +The +.B NS_GET_OWNER_UID +.\" commit 015bb305b8ebe8d601a238ab70ebdc394c7a19ba +operation (available since Linux 4.11) can be used to discover +the owner user ID of a user namespace (i.e., the effective user ID +of the process that created the user namespace). +The form of the call is: +.PP +.in +4n +.EX +uid_t uid; +ioctl(fd, NS_GET_OWNER_UID, &uid); +.EE +.in +.PP +.I fd +refers to a +.IR /proc/ pid /ns/user +file. +.PP +The owner user ID is returned in the +.I uid_t +pointed to by the third argument. +.PP +This operation can fail with the following error: +.TP +.B EINVAL +.I fd +does not refer to a user namespace. +.SH ERRORS +Any of the above +.BR ioctl () +operations can return the following errors: +.TP +.B ENOTTY +.I fd +does not refer to a +.IR /proc/ pid /ns/ * +file. +.SH STANDARDS +Linux. +.SH EXAMPLES +The example shown below uses the +.BR ioctl (2) +operations described above to perform simple +discovery of namespace relationships. +The following shell sessions show various examples of the use +of this program. +.PP +Trying to get the parent of the initial user namespace fails, +since it has no parent: +.PP +.in +4n +.EX +$ \fB./ns_show /proc/self/ns/user p\fP +The parent namespace is outside your namespace scope +.EE +.in +.PP +Create a process running +.BR sleep (1) +that resides in new user and UTS namespaces, +and show that the new UTS namespace is associated with the new user namespace: +.PP +.in +4n +.EX +$ \fBunshare \-Uu sleep 1000 &\fP +[1] 23235 +$ \fB./ns_show /proc/23235/ns/uts u\fP +Device/Inode of owning user namespace is: [0,3] / 4026532448 +$ \fBreadlink /proc/23235/ns/user\fP +user:[4026532448] +.EE +.in +.PP +Then show that the parent of the new user namespace in the preceding +example is the initial user namespace: +.PP +.in +4n +.EX +$ \fBreadlink /proc/self/ns/user\fP +user:[4026531837] +$ \fB./ns_show /proc/23235/ns/user p\fP +Device/Inode of parent namespace is: [0,3] / 4026531837 +.EE +.in +.PP +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. +.PP +.in +4n +.EX +$ \fBPS1="sh2$ " unshare \-U bash\fP +sh2$ \fB./ns_show /proc/self/ns/user p\fP +The parent namespace is outside your namespace scope +sh2$ \fB./ns_show /proc/self/ns/uts u\fP +The owning user namespace is outside your namespace scope +.EE +.in +.SS Program source +\& +.\" SRC BEGIN (ns_show.c) +.EX +/* ns_show.c +\& + Licensed under the GNU General Public License v2 or later. +*/ +#include <errno.h> +#include <fcntl.h> +#include <linux/nsfs.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/sysmacros.h> +#include <unistd.h> +\& +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]\en", + argv[0]); + fprintf(stderr, "\enDisplay the result of one or both " + "of NS_GET_USERNS (u) or NS_GET_PARENT (p)\en" + "for the specified /proc/[pid]/ns/[file]. If neither " + "\[aq]p\[aq] nor \[aq]u\[aq] is specified,\en" + "NS_GET_USERNS is the default.\en"); + exit(EXIT_FAILURE); + } +\& + /* Obtain a file descriptor for the \[aq]ns\[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], \[aq]u\[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\en"); + else + perror("ioctl\-NS_GET_USERNS"); + exit(EXIT_FAILURE); + } +\& + if (fstat(userns_fd, &sb) == \-1) { + perror("fstat\-userns"); + exit(EXIT_FAILURE); + } + printf("Device/Inode of owning user namespace is: " + "[%x,%x] / %ju\en", + major(sb.st_dev), + minor(sb.st_dev), + (uintmax_t) 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], \[aq]p\[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\en"); + else if (errno == EPERM) + printf("The parent namespace is outside " + "your namespace scope\en"); + else + perror("ioctl\-NS_GET_PARENT"); + exit(EXIT_FAILURE); + } +\& + if (fstat(parent_fd, &sb) == \-1) { + perror("fstat\-parentns"); + exit(EXIT_FAILURE); + } + printf("Device/Inode of parent namespace is: [%x,%x] / %ju\en", + major(sb.st_dev), + minor(sb.st_dev), + (uintmax_t) sb.st_ino); +\& + close(parent_fd); + } +\& + exit(EXIT_SUCCESS); +} +.EE +.\" SRC END +.SH SEE ALSO +.BR fstat (2), +.BR ioctl (2), +.BR proc (5), +.BR namespaces (7) |