mirror of https://github.com/mkerrisk/man-pages
namespaces.7: Remove content split out into ioctl_ns(2)
Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This commit is contained in:
parent
008f58d5e8
commit
e0ab72cb98
|
@ -323,272 +323,16 @@ and
|
||||||
Use of UTS namespaces requires a kernel that is configured with the
|
Use of UTS namespaces requires a kernel that is configured with the
|
||||||
.B CONFIG_UTS_NS
|
.B CONFIG_UTS_NS
|
||||||
option.
|
option.
|
||||||
.\"
|
.fi
|
||||||
.\" ============================================================
|
|
||||||
.\"
|
|
||||||
.SS Discovering namespace relationships
|
|
||||||
Since Linux 4.9,
|
|
||||||
.\" commit bcac25a58bfc6bd79191ac5d7afb49bea96da8c9
|
|
||||||
.\" commit 6786741dbf99e44fb0c0ed85a37582b8a26f1c3b
|
|
||||||
.\" commit a7306ed8d94af729ecef8b6e37506a1c6fc14788
|
|
||||||
.\" commit 6ad92bf63e45f97e306da48cd1cbce6e4fef1e5d
|
|
||||||
two
|
|
||||||
.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:
|
|
||||||
|
|
||||||
new_fd = ioctl(fd, request);
|
|
||||||
|
|
||||||
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
|
|
||||||
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
|
|
||||||
The new file descriptor returned by these operations is opened with the
|
|
||||||
.BR O_RDONLY
|
|
||||||
and
|
|
||||||
.BR 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.
|
|
||||||
|
|
||||||
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 EXAMPLE section for an example of the use of these operations.
|
|
||||||
.SH CONFORMING TO
|
|
||||||
Namespaces are a Linux-specific feature.
|
|
||||||
.SH EXAMPLE
|
.SH EXAMPLE
|
||||||
For one example,
|
See
|
||||||
.BR user_namespaces (7).
|
.BR user_namespaces (7).
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
Trying to get the parent of the initial user namespace fails,
|
|
||||||
since it has no parent:
|
|
||||||
|
|
||||||
.nf
|
|
||||||
.in +4n
|
|
||||||
$ \fB./ns_show /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 the new UTS namespace is associated with the new user namespace:
|
|
||||||
|
|
||||||
.nf
|
|
||||||
.in +4n
|
|
||||||
$ \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]
|
|
||||||
.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_show /proc/23235/ns/user p\fP
|
|
||||||
Device/Inode of parent namespace is: [0,3] / 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
|
|
||||||
$ \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
|
|
||||||
.in
|
|
||||||
.fi
|
|
||||||
.SS Program source
|
|
||||||
\&
|
|
||||||
.nf
|
|
||||||
/* ns_show.c
|
|
||||||
|
|
||||||
Licensed under the GNU General Public License v2 or later.
|
|
||||||
*/
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <sys/sysmacros.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("Device/Inode of owning user namespace is: "
|
|
||||||
"[%lx,%lx] / %ld\\n",
|
|
||||||
(long) major(sb.st_dev), (long) minor(sb.st_dev),
|
|
||||||
(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("Device/Inode of parent namespace is: [%lx,%lx] / %ld\\n",
|
|
||||||
(long) major(sb.st_dev), (long) minor(sb.st_dev),
|
|
||||||
(long) sb.st_ino);
|
|
||||||
|
|
||||||
close(parent_fd);
|
|
||||||
}
|
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
|
||||||
}
|
|
||||||
.fi
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR nsenter (1),
|
.BR nsenter (1),
|
||||||
.BR readlink (1),
|
.BR readlink (1),
|
||||||
.BR unshare (1),
|
.BR unshare (1),
|
||||||
.BR clone (2),
|
.BR clone (2),
|
||||||
|
.BR ioctl_ns (2),
|
||||||
.BR setns (2),
|
.BR setns (2),
|
||||||
.BR unshare (2),
|
.BR unshare (2),
|
||||||
.BR proc (5),
|
.BR proc (5),
|
||||||
|
|
Loading…
Reference in New Issue