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