1ioctl_ns(2)                   System Calls Manual                  ioctl_ns(2)
2
3
4

NAME

6       ioctl_ns - ioctl() operations for Linux namespaces
7

DESCRIPTION

9   Discovering namespace relationships
10       The  following  ioctl(2)  operations are provided to allow discovery of
11       namespace relationships (see user_namespaces(7) and pid_namespaces(7)).
12       The form of the calls is:
13
14           new_fd = ioctl(fd, request);
15
16       In  each case, fd refers to a /proc/pid/ns/* file.  Both operations re‐
17       turn a new file descriptor on success.
18
19       NS_GET_USERNS (since Linux 4.9)
20              Returns a file descriptor that refers to the owning  user  name‐
21              space for the namespace referred to by fd.
22
23       NS_GET_PARENT (since Linux 4.9)
24              Returns a file descriptor that refers to the parent namespace of
25              the namespace referred to by fd.  This operation is  valid  only
26              for  hierarchical  namespaces  (i.e.,  PID and user namespaces).
27              For  user   namespaces,   NS_GET_PARENT   is   synonymous   with
28              NS_GET_USERNS.
29
30       The new file descriptor returned by these operations is opened with the
31       O_RDONLY and O_CLOEXEC (close-on-exec; see fcntl(2)) flags.
32
33       By applying fstat(2) to the returned file  descriptor,  one  obtains  a
34       stat structure whose st_dev (resident device) and st_ino (inode number)
35       fields together identify the owning/parent namespace.  This inode  num‐
36       ber    can    be   matched   with   the   inode   number   of   another
37       /proc/pid/ns/{pid,user} file to determine  whether  that  is  the  own‐
38       ing/parent namespace.
39
40       Either of these ioctl(2) operations can fail with the following errors:
41
42       EPERM  The  requested  namespace  is  outside of the caller's namespace
43              scope.  This error can occur if, for example,  the  owning  user
44              namespace is an ancestor of the caller's current user namespace.
45              It can also occur on attempts to obtain the parent of  the  ini‐
46              tial user or PID namespace.
47
48       ENOTTY The operation is not supported by this kernel version.
49
50       Additionally,  the  NS_GET_PARENT operation can fail with the following
51       error:
52
53       EINVAL fd refers to a nonhierarchical namespace.
54
55       See the EXAMPLES section for an example of the use of these operations.
56
57   Discovering the namespace type
58       The NS_GET_NSTYPE operation (available since Linux 4.11) can be used to
59       discover the type of namespace referred to by the file descriptor fd:
60
61           nstype = ioctl(fd, NS_GET_NSTYPE);
62
63       fd refers to a /proc/pid/ns/* file.
64
65       The  return value is one of the CLONE_NEW* values that can be specified
66       to clone(2) or unshare(2) in order to create a namespace.
67
68   Discovering the owner of a user namespace
69       The NS_GET_OWNER_UID operation (available since Linux 4.11) can be used
70       to  discover the owner user ID of a user namespace (i.e., the effective
71       user ID of the process that created the user namespace).  The  form  of
72       the call is:
73
74           uid_t uid;
75           ioctl(fd, NS_GET_OWNER_UID, &uid);
76
77       fd refers to a /proc/pid/ns/user file.
78
79       The  owner user ID is returned in the uid_t pointed to by the third ar‐
80       gument.
81
82       This operation can fail with the following error:
83
84       EINVAL fd does not refer to a user namespace.
85

ERRORS

87       Any of the above ioctl() operations can return the following errors:
88
89       ENOTTY fd does not refer to a /proc/pid/ns/* file.
90

STANDARDS

92       Linux.
93

EXAMPLES

95       The example shown below uses the ioctl(2) operations described above to
96       perform  simple  discovery  of  namespace relationships.  The following
97       shell sessions show various examples of the use of this program.
98
99       Trying to get the parent of the initial user namespace fails, since  it
100       has no parent:
101
102           $ ./ns_show /proc/self/ns/user p
103           The parent namespace is outside your namespace scope
104
105       Create  a  process  running  sleep(1)  that resides in new user and UTS
106       namespaces, and show that the new UTS namespace is associated with  the
107       new user namespace:
108
109           $ unshare -Uu sleep 1000 &
110           [1] 23235
111           $ ./ns_show /proc/23235/ns/uts u
112           Device/Inode of owning user namespace is: [0,3] / 4026532448
113           $ readlink /proc/23235/ns/user
114           user:[4026532448]
115
116       Then  show  that  the parent of the new user namespace in the preceding
117       example is the initial user namespace:
118
119           $ readlink /proc/self/ns/user
120           user:[4026531837]
121           $ ./ns_show /proc/23235/ns/user p
122           Device/Inode of parent namespace is: [0,3] / 4026531837
123
124       Start a shell in a new user namespace, and show that from  within  this
125       shell,  the  parent user namespace can't be discovered.  Similarly, the
126       UTS namespace (which is associated with  the  initial  user  namespace)
127       can't be discovered.
128
129           $ PS1="sh2$ " unshare -U bash
130           sh2$ ./ns_show /proc/self/ns/user p
131           The parent namespace is outside your namespace scope
132           sh2$ ./ns_show /proc/self/ns/uts u
133           The owning user namespace is outside your namespace scope
134
135   Program source
136
137       /* ns_show.c
138
139          Licensed under the GNU General Public License v2 or later.
140       */
141       #include <errno.h>
142       #include <fcntl.h>
143       #include <linux/nsfs.h>
144       #include <stdint.h>
145       #include <stdio.h>
146       #include <stdlib.h>
147       #include <string.h>
148       #include <sys/ioctl.h>
149       #include <sys/stat.h>
150       #include <sys/sysmacros.h>
151       #include <unistd.h>
152
153       int
154       main(int argc, char *argv[])
155       {
156           int          fd, userns_fd, parent_fd;
157           struct stat  sb;
158
159           if (argc < 2) {
160               fprintf(stderr, "Usage: %s /proc/[pid]/ns/[file] [p|u]\n",
161                       argv[0]);
162               fprintf(stderr, "\nDisplay the result of one or both "
163                       "of NS_GET_USERNS (u) or NS_GET_PARENT (p)\n"
164                       "for the specified /proc/[pid]/ns/[file]. If neither "
165                       "'p' nor 'u' is specified,\n"
166                       "NS_GET_USERNS is the default.\n");
167               exit(EXIT_FAILURE);
168           }
169
170           /* Obtain a file descriptor for the 'ns' file specified
171              in argv[1]. */
172
173           fd = open(argv[1], O_RDONLY);
174           if (fd == -1) {
175               perror("open");
176               exit(EXIT_FAILURE);
177           }
178
179           /* Obtain a file descriptor for the owning user namespace and
180              then obtain and display the inode number of that namespace. */
181
182           if (argc < 3 || strchr(argv[2], 'u')) {
183               userns_fd = ioctl(fd, NS_GET_USERNS);
184
185               if (userns_fd == -1) {
186                   if (errno == EPERM)
187                       printf("The owning user namespace is outside "
188                              "your namespace scope\n");
189                   else
190                      perror("ioctl-NS_GET_USERNS");
191                   exit(EXIT_FAILURE);
192                }
193
194               if (fstat(userns_fd, &sb) == -1) {
195                   perror("fstat-userns");
196                   exit(EXIT_FAILURE);
197               }
198               printf("Device/Inode of owning user namespace is: "
199                      "[%x,%x] / %ju\n",
200                      major(sb.st_dev),
201                      minor(sb.st_dev),
202                      (uintmax_t) sb.st_ino);
203
204               close(userns_fd);
205           }
206
207           /* Obtain a file descriptor for the parent namespace and
208              then obtain and display the inode number of that namespace. */
209
210           if (argc > 2 && strchr(argv[2], 'p')) {
211               parent_fd = ioctl(fd, NS_GET_PARENT);
212
213               if (parent_fd == -1) {
214                   if (errno == EINVAL)
215                       printf("Can' get parent namespace of a "
216                              "nonhierarchical namespace\n");
217                   else if (errno == EPERM)
218                       printf("The parent namespace is outside "
219                              "your namespace scope\n");
220                   else
221                       perror("ioctl-NS_GET_PARENT");
222                   exit(EXIT_FAILURE);
223               }
224
225               if (fstat(parent_fd, &sb) == -1) {
226                   perror("fstat-parentns");
227                   exit(EXIT_FAILURE);
228               }
229               printf("Device/Inode of parent namespace is: [%x,%x] / %ju\n",
230                      major(sb.st_dev),
231                      minor(sb.st_dev),
232                      (uintmax_t) sb.st_ino);
233
234               close(parent_fd);
235           }
236
237           exit(EXIT_SUCCESS);
238       }
239

SEE ALSO

241       fstat(2), ioctl(2), proc(5), namespaces(7)
242
243
244
245Linux man-pages 6.04              2023-04-03                       ioctl_ns(2)
Impressum