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 names‐
21 pace 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 EXAMPLE 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
80 argument.
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 <stdlib.h>
143 #include <unistd.h>
144 #include <stdio.h>
145 #include <fcntl.h>
146 #include <string.h>
147 #include <sys/stat.h>
148 #include <sys/ioctl.h>
149 #include <errno.h>
150 #include <sys/sysmacros.h>
151
152 #ifndef NS_GET_USERNS
153 #define NSIO 0xb7
154 #define NS_GET_USERNS _IO(NSIO, 0x1)
155 #define NS_GET_PARENT _IO(NSIO, 0x2)
156 #endif
157
158 int
159 main(int argc, char *argv[])
160 {
161 int fd, userns_fd, parent_fd;
162 struct stat sb;
163
164 if (argc < 2) {
165 fprintf(stderr, "Usage: %s /proc/[pid]/ns/[file] [p|u]\n",
166 argv[0]);
167 fprintf(stderr, "\nDisplay the result of one or both "
168 "of NS_GET_USERNS (u) or NS_GET_PARENT (p)\n"
169 "for the specified /proc/[pid]/ns/[file]. If neither "
170 "'p' nor 'u' is specified,\n"
171 "NS_GET_USERNS is the default.\n");
172 exit(EXIT_FAILURE);
173 }
174
175 /* Obtain a file descriptor for the 'ns' file specified
176 in argv[1] */
177
178 fd = open(argv[1], O_RDONLY);
179 if (fd == -1) {
180 perror("open");
181 exit(EXIT_FAILURE);
182 }
183
184 /* Obtain a file descriptor for the owning user namespace and
185 then obtain and display the inode number of that namespace */
186
187 if (argc < 3 || strchr(argv[2], 'u')) {
188 userns_fd = ioctl(fd, NS_GET_USERNS);
189
190 if (userns_fd == -1) {
191 if (errno == EPERM)
192 printf("The owning user namespace is outside "
193 "your namespace scope\n");
194 else
195 perror("ioctl-NS_GET_USERNS");
196 exit(EXIT_FAILURE);
197 }
198
199 if (fstat(userns_fd, &sb) == -1) {
200 perror("fstat-userns");
201 exit(EXIT_FAILURE);
202 }
203 printf("Device/Inode of owning user namespace is: "
204 "[%lx,%lx] / %ld\n",
205 (long) major(sb.st_dev), (long) minor(sb.st_dev),
206 (long) sb.st_ino);
207
208 close(userns_fd);
209 }
210
211 /* Obtain a file descriptor for the parent namespace and
212 then obtain and display the inode number of that namespace */
213
214 if (argc > 2 && strchr(argv[2], 'p')) {
215 parent_fd = ioctl(fd, NS_GET_PARENT);
216
217 if (parent_fd == -1) {
218 if (errno == EINVAL)
219 printf("Can' get parent namespace of a "
220 "nonhierarchical namespace\n");
221 else if (errno == EPERM)
222 printf("The parent namespace is outside "
223 "your namespace scope\n");
224 else
225 perror("ioctl-NS_GET_PARENT");
226 exit(EXIT_FAILURE);
227 }
228
229 if (fstat(parent_fd, &sb) == -1) {
230 perror("fstat-parentns");
231 exit(EXIT_FAILURE);
232 }
233 printf("Device/Inode of parent namespace is: [%lx,%lx] / %ld\n",
234 (long) major(sb.st_dev), (long) minor(sb.st_dev),
235 (long) sb.st_ino);
236
237 close(parent_fd);
238 }
239
240 exit(EXIT_SUCCESS);
241 }
242
244 fstat(2), ioctl(2), proc(5), namespaces(7)
245
247 This page is part of release 5.07 of the Linux man-pages project. A
248 description of the project, information about reporting bugs, and the
249 latest version of this page, can be found at
250 https://www.kernel.org/doc/man-pages/.
251
252
253
254Linux 2020-06-09 IOCTL_NS(2)