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