]> git.ipfire.org Git - thirdparty/man-pages.git/blob - man2/ioctl_ns.2
2d9d280201910d7420f7c6e0baa102e0b0264c15
[thirdparty/man-pages.git] / man2 / ioctl_ns.2
1 .\" Copyright (c) 2017 by Michael Kerrisk <mtk.manpages@gmail.com>
2 .\"
3 .\" SPDX-License-Identifier: Linux-man-pages-copyleft
4 .\"
5 .\"
6 .TH IOCTL_NS 2 2021-03-22 "Linux" "Linux Programmer's Manual"
7 .SH NAME
8 ioctl_ns \- ioctl() operations for Linux namespaces
9 .SH DESCRIPTION
10 .\" ============================================================
11 .\"
12 .SS Discovering namespace relationships
13 The following
14 .BR ioctl (2)
15 operations are provided to allow discovery of namespace relationships (see
16 .BR user_namespaces (7)
17 and
18 .BR pid_namespaces (7)).
19 The form of the calls is:
20 .PP
21 .in +4n
22 .EX
23 new_fd = ioctl(fd, request);
24 .EE
25 .in
26 .PP
27 In each case,
28 .I fd
29 refers to a
30 .IR /proc/[pid]/ns/*
31 file.
32 Both operations return a new file descriptor on success.
33 .TP
34 .BR NS_GET_USERNS " (since Linux 4.9)"
35 .\" commit bcac25a58bfc6bd79191ac5d7afb49bea96da8c9
36 .\" commit 6786741dbf99e44fb0c0ed85a37582b8a26f1c3b
37 Returns a file descriptor that refers to the owning user namespace
38 for the namespace referred to by
39 .IR fd .
40 .TP
41 .BR NS_GET_PARENT " (since Linux 4.9)"
42 .\" commit a7306ed8d94af729ecef8b6e37506a1c6fc14788
43 Returns a file descriptor that refers to the parent namespace of
44 the namespace referred to by
45 .IR fd .
46 This operation is valid only for hierarchical namespaces
47 (i.e., PID and user namespaces).
48 For user namespaces,
49 .BR NS_GET_PARENT
50 is synonymous with
51 .BR NS_GET_USERNS .
52 .PP
53 The new file descriptor returned by these operations is opened with the
54 .BR O_RDONLY
55 and
56 .BR O_CLOEXEC
57 (close-on-exec; see
58 .BR fcntl (2))
59 flags.
60 .PP
61 By applying
62 .BR fstat (2)
63 to the returned file descriptor, one obtains a
64 .I stat
65 structure whose
66 .I st_dev
67 (resident device) and
68 .I st_ino
69 (inode number) fields together identify the owning/parent namespace.
70 This inode number can be matched with the inode number of another
71 .IR /proc/[pid]/ns/{pid,user}
72 file to determine whether that is the owning/parent namespace.
73 .PP
74 Either of these
75 .BR ioctl (2)
76 operations can fail with the following errors:
77 .TP
78 .B EPERM
79 The requested namespace is outside of the caller's namespace scope.
80 This error can occur if, for example, the owning user namespace is an
81 ancestor of the caller's current user namespace.
82 It can also occur on attempts to obtain the parent of the initial
83 user or PID namespace.
84 .TP
85 .B ENOTTY
86 The operation is not supported by this kernel version.
87 .PP
88 Additionally, the
89 .B NS_GET_PARENT
90 operation can fail with the following error:
91 .TP
92 .B EINVAL
93 .I fd
94 refers to a nonhierarchical namespace.
95 .PP
96 See the EXAMPLES section for an example of the use of these operations.
97 .\" ============================================================
98 .\"
99 .SS Discovering the namespace type
100 The
101 .B NS_GET_NSTYPE
102 .\" commit e5ff5ce6e20ee22511398bb31fb912466cf82a36
103 operation (available since Linux 4.11) can be used to discover
104 the type of namespace referred to by the file descriptor
105 .IR fd :
106 .PP
107 .in +4n
108 .EX
109 nstype = ioctl(fd, NS_GET_NSTYPE);
110 .EE
111 .in
112 .PP
113 .I fd
114 refers to a
115 .IR /proc/[pid]/ns/*
116 file.
117 .PP
118 The return value is one of the
119 .BR CLONE_NEW*
120 values that can be specified to
121 .BR clone (2)
122 or
123 .BR unshare (2)
124 in order to create a namespace.
125 .\" ============================================================
126 .\"
127 .SS Discovering the owner of a user namespace
128 The
129 .B NS_GET_OWNER_UID
130 .\" commit 015bb305b8ebe8d601a238ab70ebdc394c7a19ba
131 operation (available since Linux 4.11) can be used to discover
132 the owner user ID of a user namespace (i.e., the effective user ID
133 of the process that created the user namespace).
134 The form of the call is:
135 .PP
136 .in +4n
137 .EX
138 uid_t uid;
139 ioctl(fd, NS_GET_OWNER_UID, &uid);
140 .EE
141 .in
142 .PP
143 .I fd
144 refers to a
145 .IR /proc/[pid]/ns/user
146 file.
147 .PP
148 The owner user ID is returned in the
149 .I uid_t
150 pointed to by the third argument.
151 .PP
152 This operation can fail with the following error:
153 .TP
154 .B EINVAL
155 .I fd
156 does not refer to a user namespace.
157 .SH ERRORS
158 Any of the above
159 .BR ioctl ()
160 operations can return the following errors:
161 .TP
162 .B ENOTTY
163 .I fd
164 does not refer to a
165 .I /proc/[pid]/ns/*
166 file.
167 .SH CONFORMING TO
168 Namespaces and the operations described on this page are a Linux-specific.
169 .SH EXAMPLES
170 The example shown below uses the
171 .BR ioctl (2)
172 operations described above to perform simple
173 discovery of namespace relationships.
174 The following shell sessions show various examples of the use
175 of this program.
176 .PP
177 Trying to get the parent of the initial user namespace fails,
178 since it has no parent:
179 .PP
180 .in +4n
181 .EX
182 $ \fB./ns_show /proc/self/ns/user p\fP
183 The parent namespace is outside your namespace scope
184 .EE
185 .in
186 .PP
187 Create a process running
188 .BR sleep (1)
189 that resides in new user and UTS namespaces,
190 and show that the new UTS namespace is associated with the new user namespace:
191 .PP
192 .in +4n
193 .EX
194 $ \fBunshare \-Uu sleep 1000 &\fP
195 [1] 23235
196 $ \fB./ns_show /proc/23235/ns/uts u\fP
197 Device/Inode of owning user namespace is: [0,3] / 4026532448
198 $ \fBreadlink /proc/23235/ns/user\fP
199 user:[4026532448]
200 .EE
201 .in
202 .PP
203 Then show that the parent of the new user namespace in the preceding
204 example is the initial user namespace:
205 .PP
206 .in +4n
207 .EX
208 $ \fBreadlink /proc/self/ns/user\fP
209 user:[4026531837]
210 $ \fB./ns_show /proc/23235/ns/user p\fP
211 Device/Inode of parent namespace is: [0,3] / 4026531837
212 .EE
213 .in
214 .PP
215 Start a shell in a new user namespace, and show that from within
216 this shell, the parent user namespace can't be discovered.
217 Similarly, the UTS namespace
218 (which is associated with the initial user namespace)
219 can't be discovered.
220 .PP
221 .in +4n
222 .EX
223 $ \fBPS1="sh2$ " unshare \-U bash\fP
224 sh2$ \fB./ns_show /proc/self/ns/user p\fP
225 The parent namespace is outside your namespace scope
226 sh2$ \fB./ns_show /proc/self/ns/uts u\fP
227 The owning user namespace is outside your namespace scope
228 .EE
229 .in
230 .SS Program source
231 \&
232 .EX
233 /* ns_show.c
234
235 Licensed under the GNU General Public License v2 or later.
236 */
237 #include <stdint.h>
238 #include <stdlib.h>
239 #include <unistd.h>
240 #include <stdio.h>
241 #include <fcntl.h>
242 #include <string.h>
243 #include <sys/stat.h>
244 #include <sys/ioctl.h>
245 #include <errno.h>
246 #include <sys/sysmacros.h>
247
248 #ifndef NS_GET_USERNS
249 #define NSIO 0xb7
250 #define NS_GET_USERNS _IO(NSIO, 0x1)
251 #define NS_GET_PARENT _IO(NSIO, 0x2)
252 #endif
253
254 int
255 main(int argc, char *argv[])
256 {
257 int fd, userns_fd, parent_fd;
258 struct stat sb;
259
260 if (argc < 2) {
261 fprintf(stderr, "Usage: %s /proc/[pid]/ns/[file] [p|u]\en",
262 argv[0]);
263 fprintf(stderr, "\enDisplay the result of one or both "
264 "of NS_GET_USERNS (u) or NS_GET_PARENT (p)\en"
265 "for the specified /proc/[pid]/ns/[file]. If neither "
266 "\(aqp\(aq nor \(aqu\(aq is specified,\en"
267 "NS_GET_USERNS is the default.\en");
268 exit(EXIT_FAILURE);
269 }
270
271 /* Obtain a file descriptor for the \(aqns\(aq file specified
272 in argv[1]. */
273
274 fd = open(argv[1], O_RDONLY);
275 if (fd == \-1) {
276 perror("open");
277 exit(EXIT_FAILURE);
278 }
279
280 /* Obtain a file descriptor for the owning user namespace and
281 then obtain and display the inode number of that namespace. */
282
283 if (argc < 3 || strchr(argv[2], \(aqu\(aq)) {
284 userns_fd = ioctl(fd, NS_GET_USERNS);
285
286 if (userns_fd == \-1) {
287 if (errno == EPERM)
288 printf("The owning user namespace is outside "
289 "your namespace scope\en");
290 else
291 perror("ioctl\-NS_GET_USERNS");
292 exit(EXIT_FAILURE);
293 }
294
295 if (fstat(userns_fd, &sb) == \-1) {
296 perror("fstat\-userns");
297 exit(EXIT_FAILURE);
298 }
299 printf("Device/Inode of owning user namespace is: "
300 "[%jx,%jx] / %ju\en",
301 (uintmax_t) major(sb.st_dev),
302 (uintmax_t) minor(sb.st_dev),
303 (uintmax_t) sb.st_ino);
304
305 close(userns_fd);
306 }
307
308 /* Obtain a file descriptor for the parent namespace and
309 then obtain and display the inode number of that namespace. */
310
311 if (argc > 2 && strchr(argv[2], \(aqp\(aq)) {
312 parent_fd = ioctl(fd, NS_GET_PARENT);
313
314 if (parent_fd == \-1) {
315 if (errno == EINVAL)
316 printf("Can\(aq get parent namespace of a "
317 "nonhierarchical namespace\en");
318 else if (errno == EPERM)
319 printf("The parent namespace is outside "
320 "your namespace scope\en");
321 else
322 perror("ioctl\-NS_GET_PARENT");
323 exit(EXIT_FAILURE);
324 }
325
326 if (fstat(parent_fd, &sb) == \-1) {
327 perror("fstat\-parentns");
328 exit(EXIT_FAILURE);
329 }
330 printf("Device/Inode of parent namespace is: [%jx,%jx] / %ju\en",
331 (uintmax_t) major(sb.st_dev),
332 (uintmax_t) minor(sb.st_dev),
333 (uintmax_t) sb.st_ino);
334
335 close(parent_fd);
336 }
337
338 exit(EXIT_SUCCESS);
339 }
340 .EE
341 .SH SEE ALSO
342 .BR fstat (2),
343 .BR ioctl (2),
344 .BR proc (5),
345 .BR namespaces (7)