xref: /linux/tools/testing/selftests/pidfd/pidfd_setns_test.c (revision 1260ed77798502de9c98020040d2995008de10cc)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #define _GNU_SOURCE
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <limits.h>
7 #include <linux/types.h>
8 #include <sched.h>
9 #include <signal.h>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <syscall.h>
14 #include <sys/prctl.h>
15 #include <sys/wait.h>
16 #include <unistd.h>
17 #include <sys/socket.h>
18 #include <sys/stat.h>
19 
20 #include "pidfd.h"
21 #include "../kselftest_harness.h"
22 
23 enum {
24 	PIDFD_NS_USER,
25 	PIDFD_NS_MNT,
26 	PIDFD_NS_PID,
27 	PIDFD_NS_UTS,
28 	PIDFD_NS_IPC,
29 	PIDFD_NS_NET,
30 	PIDFD_NS_CGROUP,
31 	PIDFD_NS_PIDCLD,
32 	PIDFD_NS_TIME,
33 	PIDFD_NS_TIMECLD,
34 	PIDFD_NS_MAX
35 };
36 
37 const struct ns_info {
38 	const char *name;
39 	int flag;
40 	unsigned int pidfd_ioctl;
41 } ns_info[] = {
42 	[PIDFD_NS_USER]    = { "user",              CLONE_NEWUSER,   PIDFD_GET_USER_NAMESPACE,              },
43 	[PIDFD_NS_MNT]     = { "mnt",               CLONE_NEWNS,     PIDFD_GET_MNT_NAMESPACE,               },
44 	[PIDFD_NS_PID]     = { "pid",               CLONE_NEWPID,    PIDFD_GET_PID_NAMESPACE,               },
45 	[PIDFD_NS_UTS]     = { "uts",               CLONE_NEWUTS,    PIDFD_GET_UTS_NAMESPACE,               },
46 	[PIDFD_NS_IPC]     = { "ipc",               CLONE_NEWIPC,    PIDFD_GET_IPC_NAMESPACE,               },
47 	[PIDFD_NS_NET]     = { "net",               CLONE_NEWNET,    PIDFD_GET_NET_NAMESPACE,               },
48 	[PIDFD_NS_CGROUP]  = { "cgroup",            CLONE_NEWCGROUP, PIDFD_GET_CGROUP_NAMESPACE,            },
49 	[PIDFD_NS_TIME]	   = { "time",              CLONE_NEWTIME,   PIDFD_GET_TIME_NAMESPACE,              },
50 	[PIDFD_NS_PIDCLD]  = { "pid_for_children",  0,               PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE,  },
51 	[PIDFD_NS_TIMECLD] = { "time_for_children", 0,               PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE, },
52 };
53 
54 FIXTURE(current_nsset)
55 {
56 	pid_t pid;
57 	int pidfd;
58 	int nsfds[PIDFD_NS_MAX];
59 	int child_pidfd_derived_nsfds[PIDFD_NS_MAX];
60 
61 	pid_t child_pid_exited;
62 	int child_pidfd_exited;
63 
64 	pid_t child_pid1;
65 	int child_pidfd1;
66 	int child_nsfds1[PIDFD_NS_MAX];
67 	int child_pidfd_derived_nsfds1[PIDFD_NS_MAX];
68 
69 	pid_t child_pid2;
70 	int child_pidfd2;
71 	int child_nsfds2[PIDFD_NS_MAX];
72 	int child_pidfd_derived_nsfds2[PIDFD_NS_MAX];
73 };
74 
75 static bool switch_timens(void)
76 {
77 	int fd, ret;
78 
79 	if (unshare(CLONE_NEWTIME))
80 		return false;
81 
82 	fd = open("/proc/self/ns/time_for_children", O_RDONLY | O_CLOEXEC);
83 	if (fd < 0)
84 		return false;
85 
86 	ret = setns(fd, CLONE_NEWTIME);
87 	close(fd);
88 	return ret == 0;
89 }
90 
91 FIXTURE_SETUP(current_nsset)
92 {
93 	int i, proc_fd, ret;
94 	int ipc_sockets[2];
95 	char c;
96 
97 	for (i = 0; i < PIDFD_NS_MAX; i++) {
98 		self->nsfds[i]				= -EBADF;
99 		self->child_nsfds1[i]			= -EBADF;
100 		self->child_nsfds2[i]			= -EBADF;
101 		self->child_pidfd_derived_nsfds[i]	= -EBADF;
102 		self->child_pidfd_derived_nsfds1[i]	= -EBADF;
103 		self->child_pidfd_derived_nsfds2[i]	= -EBADF;
104 	}
105 
106 	proc_fd = open("/proc/self/ns", O_DIRECTORY | O_CLOEXEC);
107 	ASSERT_GE(proc_fd, 0) {
108 		TH_LOG("%m - Failed to open /proc/self/ns");
109 	}
110 
111 	self->pid = getpid();
112 	self->pidfd = sys_pidfd_open(self->pid, 0);
113 	EXPECT_GT(self->pidfd, 0) {
114 		TH_LOG("%m - Failed to open pidfd for process %d", self->pid);
115 	}
116 
117 	for (i = 0; i < PIDFD_NS_MAX; i++) {
118 		const struct ns_info *info = &ns_info[i];
119 		self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC);
120 		if (self->nsfds[i] < 0) {
121 			EXPECT_EQ(errno, ENOENT) {
122 				TH_LOG("%m - Failed to open %s namespace for process %d",
123 				       info->name, self->pid);
124 			}
125 		}
126 
127 		self->child_pidfd_derived_nsfds[i] = ioctl(self->pidfd, info->pidfd_ioctl, 0);
128 		if (self->child_pidfd_derived_nsfds[i] < 0) {
129 			EXPECT_EQ(errno, EOPNOTSUPP) {
130 				TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
131 				       info->name, self->pid);
132 			}
133 		}
134 	}
135 
136 	/* Create task that exits right away. */
137 	self->child_pid_exited = create_child(&self->child_pidfd_exited, 0);
138 	EXPECT_GE(self->child_pid_exited, 0);
139 
140 	if (self->child_pid_exited == 0) {
141 		if (self->nsfds[PIDFD_NS_USER] >= 0 && unshare(CLONE_NEWUSER) < 0)
142 			_exit(EXIT_FAILURE);
143 		if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0)
144 			_exit(EXIT_FAILURE);
145 		_exit(EXIT_SUCCESS);
146 	}
147 
148 	ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, NULL, WEXITED | WNOWAIT), 0);
149 
150 	self->pidfd = sys_pidfd_open(self->pid, 0);
151 	EXPECT_GE(self->pidfd, 0) {
152 		TH_LOG("%m - Failed to open pidfd for process %d", self->pid);
153 	}
154 
155 	ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
156 	EXPECT_EQ(ret, 0);
157 
158 	/* Create tasks that will be stopped. */
159 	if (self->nsfds[PIDFD_NS_USER] >= 0 && self->nsfds[PIDFD_NS_PID] >= 0)
160 		self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWUSER | CLONE_NEWPID);
161 	else if (self->nsfds[PIDFD_NS_PID] >= 0)
162 		self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWPID);
163 	else if (self->nsfds[PIDFD_NS_USER] >= 0)
164 		self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWUSER);
165 	else
166 		self->child_pid1 = create_child(&self->child_pidfd1, 0);
167 	EXPECT_GE(self->child_pid1, 0);
168 
169 	if (self->child_pid1 == 0) {
170 		close(ipc_sockets[0]);
171 
172 		if (self->nsfds[PIDFD_NS_MNT] >= 0 && unshare(CLONE_NEWNS) < 0) {
173 			TH_LOG("%m - Failed to unshare mount namespace for process %d", self->pid);
174 			_exit(EXIT_FAILURE);
175 		}
176 		if (self->nsfds[PIDFD_NS_CGROUP] >= 0 && unshare(CLONE_NEWCGROUP) < 0) {
177 			TH_LOG("%m - Failed to unshare cgroup namespace for process %d", self->pid);
178 			_exit(EXIT_FAILURE);
179 		}
180 		if (self->nsfds[PIDFD_NS_IPC] >= 0 && unshare(CLONE_NEWIPC) < 0) {
181 			TH_LOG("%m - Failed to unshare ipc namespace for process %d", self->pid);
182 			_exit(EXIT_FAILURE);
183 		}
184 		if (self->nsfds[PIDFD_NS_UTS] >= 0 && unshare(CLONE_NEWUTS) < 0) {
185 			TH_LOG("%m - Failed to unshare uts namespace for process %d", self->pid);
186 			_exit(EXIT_FAILURE);
187 		}
188 		if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0) {
189 			TH_LOG("%m - Failed to unshare net namespace for process %d", self->pid);
190 			_exit(EXIT_FAILURE);
191 		}
192 		if (self->nsfds[PIDFD_NS_TIME] >= 0 && !switch_timens()) {
193 			TH_LOG("%m - Failed to unshare time namespace for process %d", self->pid);
194 			_exit(EXIT_FAILURE);
195 		}
196 
197 		if (write_nointr(ipc_sockets[1], "1", 1) < 0)
198 			_exit(EXIT_FAILURE);
199 
200 		close(ipc_sockets[1]);
201 
202 		pause();
203 		_exit(EXIT_SUCCESS);
204 	}
205 
206 	close(ipc_sockets[1]);
207 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
208 	close(ipc_sockets[0]);
209 
210 	ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
211 	EXPECT_EQ(ret, 0);
212 
213 	if (self->nsfds[PIDFD_NS_USER] >= 0 && self->nsfds[PIDFD_NS_PID] >= 0)
214 		self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWUSER | CLONE_NEWPID);
215 	else if (self->nsfds[PIDFD_NS_PID] >= 0)
216 		self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWPID);
217 	else if (self->nsfds[PIDFD_NS_USER] >= 0)
218 		self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWUSER);
219 	else
220 		self->child_pid2 = create_child(&self->child_pidfd2, 0);
221 	EXPECT_GE(self->child_pid2, 0);
222 
223 	if (self->child_pid2 == 0) {
224 		close(ipc_sockets[0]);
225 
226 		if (self->nsfds[PIDFD_NS_MNT] >= 0 && unshare(CLONE_NEWNS) < 0) {
227 			TH_LOG("%m - Failed to unshare mount namespace for process %d", self->pid);
228 			_exit(EXIT_FAILURE);
229 		}
230 		if (self->nsfds[PIDFD_NS_CGROUP] >= 0 && unshare(CLONE_NEWCGROUP) < 0) {
231 			TH_LOG("%m - Failed to unshare cgroup namespace for process %d", self->pid);
232 			_exit(EXIT_FAILURE);
233 		}
234 		if (self->nsfds[PIDFD_NS_IPC] >= 0 && unshare(CLONE_NEWIPC) < 0) {
235 			TH_LOG("%m - Failed to unshare ipc namespace for process %d", self->pid);
236 			_exit(EXIT_FAILURE);
237 		}
238 		if (self->nsfds[PIDFD_NS_UTS] >= 0 && unshare(CLONE_NEWUTS) < 0) {
239 			TH_LOG("%m - Failed to unshare uts namespace for process %d", self->pid);
240 			_exit(EXIT_FAILURE);
241 		}
242 		if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0) {
243 			TH_LOG("%m - Failed to unshare net namespace for process %d", self->pid);
244 			_exit(EXIT_FAILURE);
245 		}
246 		if (self->nsfds[PIDFD_NS_TIME] >= 0 && !switch_timens()) {
247 			TH_LOG("%m - Failed to unshare time namespace for process %d", self->pid);
248 			_exit(EXIT_FAILURE);
249 		}
250 
251 		if (write_nointr(ipc_sockets[1], "1", 1) < 0)
252 			_exit(EXIT_FAILURE);
253 
254 		close(ipc_sockets[1]);
255 
256 		pause();
257 		_exit(EXIT_SUCCESS);
258 	}
259 
260 	close(ipc_sockets[1]);
261 	ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
262 	close(ipc_sockets[0]);
263 
264 	for (i = 0; i < PIDFD_NS_MAX; i++) {
265 		char p[100];
266 
267 		const struct ns_info *info = &ns_info[i];
268 
269 		self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC);
270 		if (self->nsfds[i] < 0) {
271 			EXPECT_EQ(errno, ENOENT) {
272 				TH_LOG("%m - Failed to open %s namespace for process %d",
273 				       info->name, self->pid);
274 			}
275 		}
276 
277 		ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s",
278 			       self->child_pid1, info->name);
279 		EXPECT_GT(ret, 0);
280 		EXPECT_LT(ret, sizeof(p));
281 
282 		self->child_nsfds1[i] = open(p, O_RDONLY | O_CLOEXEC);
283 		if (self->child_nsfds1[i] < 0) {
284 			EXPECT_EQ(errno, ENOENT) {
285 				TH_LOG("%m - Failed to open %s namespace for process %d",
286 				       info->name, self->child_pid1);
287 			}
288 		}
289 
290 		ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s",
291 			       self->child_pid2, info->name);
292 		EXPECT_GT(ret, 0);
293 		EXPECT_LT(ret, sizeof(p));
294 
295 		self->child_nsfds2[i] = open(p, O_RDONLY | O_CLOEXEC);
296 		if (self->child_nsfds2[i] < 0) {
297 			EXPECT_EQ(errno, ENOENT) {
298 				TH_LOG("%m - Failed to open %s namespace for process %d",
299 				       info->name, self->child_pid1);
300 			}
301 		}
302 
303 		self->child_pidfd_derived_nsfds1[i] = ioctl(self->child_pidfd1, info->pidfd_ioctl, 0);
304 		if (self->child_pidfd_derived_nsfds1[i] < 0) {
305 			EXPECT_EQ(errno, EOPNOTSUPP) {
306 				TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
307 				       info->name, self->child_pid1);
308 			}
309 		}
310 
311 		self->child_pidfd_derived_nsfds2[i] = ioctl(self->child_pidfd2, info->pidfd_ioctl, 0);
312 		if (self->child_pidfd_derived_nsfds2[i] < 0) {
313 			EXPECT_EQ(errno, EOPNOTSUPP) {
314 				TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
315 				       info->name, self->child_pid2);
316 			}
317 		}
318 	}
319 
320 	close(proc_fd);
321 }
322 
323 FIXTURE_TEARDOWN(current_nsset)
324 {
325 	int i;
326 
327 	ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd1,
328 					SIGKILL, NULL, 0), 0);
329 	ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd2,
330 					SIGKILL, NULL, 0), 0);
331 
332 	for (i = 0; i < PIDFD_NS_MAX; i++) {
333 		if (self->nsfds[i] >= 0)
334 			close(self->nsfds[i]);
335 		if (self->child_nsfds1[i] >= 0)
336 			close(self->child_nsfds1[i]);
337 		if (self->child_nsfds2[i] >= 0)
338 			close(self->child_nsfds2[i]);
339 		if (self->child_pidfd_derived_nsfds[i] >= 0)
340 			close(self->child_pidfd_derived_nsfds[i]);
341 		if (self->child_pidfd_derived_nsfds1[i] >= 0)
342 			close(self->child_pidfd_derived_nsfds1[i]);
343 		if (self->child_pidfd_derived_nsfds2[i] >= 0)
344 			close(self->child_pidfd_derived_nsfds2[i]);
345 	}
346 
347 	if (self->child_pidfd1 >= 0)
348 		EXPECT_EQ(0, close(self->child_pidfd1));
349 	if (self->child_pidfd2 >= 0)
350 		EXPECT_EQ(0, close(self->child_pidfd2));
351 	ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, NULL, WEXITED), 0);
352 	ASSERT_EQ(sys_waitid(P_PID, self->child_pid1, NULL, WEXITED), 0);
353 	ASSERT_EQ(sys_waitid(P_PID, self->child_pid2, NULL, WEXITED), 0);
354 }
355 
356 static int preserve_ns(const int pid, const char *ns)
357 {
358 	int ret;
359 	char path[50];
360 
361 	ret = snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns);
362 	if (ret < 0 || (size_t)ret >= sizeof(path))
363 		return -EIO;
364 
365 	return open(path, O_RDONLY | O_CLOEXEC);
366 }
367 
368 static int in_same_namespace(int ns_fd1, pid_t pid2, const char *ns)
369 {
370 	int ns_fd2 = -EBADF;
371 	int ret = -1;
372 	struct stat ns_st1, ns_st2;
373 
374 	ret = fstat(ns_fd1, &ns_st1);
375 	if (ret < 0)
376 		return -1;
377 
378 	ns_fd2 = preserve_ns(pid2, ns);
379 	if (ns_fd2 < 0)
380 		return -1;
381 
382 	ret = fstat(ns_fd2, &ns_st2);
383 	close(ns_fd2);
384 	if (ret < 0)
385 		return -1;
386 
387 	/* processes are in the same namespace */
388 	if ((ns_st1.st_dev == ns_st2.st_dev) &&
389 	    (ns_st1.st_ino == ns_st2.st_ino))
390 		return 1;
391 
392 	/* processes are in different namespaces */
393 	return 0;
394 }
395 
396 /* Test that we can't pass garbage to the kernel. */
397 TEST_F(current_nsset, invalid_flags)
398 {
399 	ASSERT_NE(setns(self->pidfd, 0), 0);
400 	EXPECT_EQ(errno, EINVAL);
401 
402 	ASSERT_NE(setns(self->pidfd, -1), 0);
403 	EXPECT_EQ(errno, EINVAL);
404 
405 	ASSERT_NE(setns(self->pidfd, CLONE_VM), 0);
406 	EXPECT_EQ(errno, EINVAL);
407 
408 	ASSERT_NE(setns(self->pidfd, CLONE_NEWUSER | CLONE_VM), 0);
409 	EXPECT_EQ(errno, EINVAL);
410 }
411 
412 /* Test that we can't attach to a task that has already exited. */
413 TEST_F(current_nsset, pidfd_exited_child)
414 {
415 	int i;
416 	pid_t pid;
417 
418 	ASSERT_NE(setns(self->child_pidfd_exited, CLONE_NEWUSER | CLONE_NEWNET),
419 		  0);
420 	EXPECT_EQ(errno, ESRCH);
421 
422 	pid = getpid();
423 	for (i = 0; i < PIDFD_NS_MAX; i++) {
424 		const struct ns_info *info = &ns_info[i];
425 		/* Verify that we haven't changed any namespaces. */
426 		if (self->nsfds[i] >= 0)
427 			ASSERT_EQ(in_same_namespace(self->nsfds[i], pid, info->name), 1);
428 	}
429 }
430 
431 TEST_F(current_nsset, pidfd_incremental_setns)
432 {
433 	int i;
434 	pid_t pid;
435 
436 	pid = getpid();
437 	for (i = 0; i < PIDFD_NS_MAX; i++) {
438 		const struct ns_info *info = &ns_info[i];
439 		int nsfd;
440 
441 		if (self->child_nsfds1[i] < 0)
442 			continue;
443 
444 		if (info->flag) {
445 			ASSERT_EQ(setns(self->child_pidfd1, info->flag), 0) {
446 				TH_LOG("%m - Failed to setns to %s namespace of %d via pidfd %d",
447 				       info->name, self->child_pid1,
448 				       self->child_pidfd1);
449 			}
450 		}
451 
452 		/* Verify that we have changed to the correct namespaces. */
453 		if (info->flag == CLONE_NEWPID)
454 			nsfd = self->nsfds[i];
455 		else
456 			nsfd = self->child_nsfds1[i];
457 		ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
458 			TH_LOG("setns failed to place us correctly into %s namespace of %d via pidfd %d",
459 			       info->name, self->child_pid1,
460 			       self->child_pidfd1);
461 		}
462 		TH_LOG("Managed to correctly setns to %s namespace of %d via pidfd %d",
463 		       info->name, self->child_pid1, self->child_pidfd1);
464 	}
465 }
466 
467 TEST_F(current_nsset, nsfd_incremental_setns)
468 {
469 	int i;
470 	pid_t pid;
471 
472 	pid = getpid();
473 	for (i = 0; i < PIDFD_NS_MAX; i++) {
474 		const struct ns_info *info = &ns_info[i];
475 		int nsfd;
476 
477 		if (self->child_nsfds1[i] < 0)
478 			continue;
479 
480 		if (info->flag) {
481 			ASSERT_EQ(setns(self->child_nsfds1[i], info->flag), 0) {
482 				TH_LOG("%m - Failed to setns to %s namespace of %d via nsfd %d",
483 				       info->name, self->child_pid1,
484 				       self->child_nsfds1[i]);
485 			}
486 		}
487 
488 		/* Verify that we have changed to the correct namespaces. */
489 		if (info->flag == CLONE_NEWPID)
490 			nsfd = self->nsfds[i];
491 		else
492 			nsfd = self->child_nsfds1[i];
493 		ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
494 			TH_LOG("setns failed to place us correctly into %s namespace of %d via nsfd %d",
495 			       info->name, self->child_pid1,
496 			       self->child_nsfds1[i]);
497 		}
498 		TH_LOG("Managed to correctly setns to %s namespace of %d via nsfd %d",
499 		       info->name, self->child_pid1, self->child_nsfds1[i]);
500 	}
501 }
502 
503 TEST_F(current_nsset, pidfd_derived_nsfd_incremental_setns)
504 {
505 	int i;
506 	pid_t pid;
507 
508 	pid = getpid();
509 	for (i = 0; i < PIDFD_NS_MAX; i++) {
510 		const struct ns_info *info = &ns_info[i];
511 		int nsfd;
512 
513 		if (self->child_pidfd_derived_nsfds1[i] < 0)
514 			continue;
515 
516 		if (info->flag) {
517 			ASSERT_EQ(setns(self->child_pidfd_derived_nsfds1[i], info->flag), 0) {
518 				TH_LOG("%m - Failed to setns to %s namespace of %d via nsfd %d",
519 				       info->name, self->child_pid1,
520 				       self->child_pidfd_derived_nsfds1[i]);
521 			}
522 		}
523 
524 		/* Verify that we have changed to the correct namespaces. */
525 		if (info->flag == CLONE_NEWPID)
526 			nsfd = self->child_pidfd_derived_nsfds[i];
527 		else
528 			nsfd = self->child_pidfd_derived_nsfds1[i];
529 		ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
530 			TH_LOG("setns failed to place us correctly into %s namespace of %d via nsfd %d",
531 			       info->name, self->child_pid1,
532 			       self->child_pidfd_derived_nsfds1[i]);
533 		}
534 		TH_LOG("Managed to correctly setns to %s namespace of %d via nsfd %d",
535 		       info->name, self->child_pid1, self->child_pidfd_derived_nsfds1[i]);
536 	}
537 }
538 
539 TEST_F(current_nsset, pidfd_one_shot_setns)
540 {
541 	unsigned flags = 0;
542 	int i;
543 	pid_t pid;
544 
545 	for (i = 0; i < PIDFD_NS_MAX; i++) {
546 		const struct ns_info *info = &ns_info[i];
547 
548 		if (self->child_nsfds1[i] < 0)
549 			continue;
550 
551 		flags |= info->flag;
552 		TH_LOG("Adding %s namespace of %d to list of namespaces to attach to",
553 		       info->name, self->child_pid1);
554 	}
555 
556 	ASSERT_EQ(setns(self->child_pidfd1, flags), 0) {
557 		TH_LOG("%m - Failed to setns to namespaces of %d",
558 		       self->child_pid1);
559 	}
560 
561 	pid = getpid();
562 	for (i = 0; i < PIDFD_NS_MAX; i++) {
563 		const struct ns_info *info = &ns_info[i];
564 		int nsfd;
565 
566 		if (self->child_nsfds1[i] < 0)
567 			continue;
568 
569 		/* Verify that we have changed to the correct namespaces. */
570 		if (info->flag == CLONE_NEWPID)
571 			nsfd = self->nsfds[i];
572 		else
573 			nsfd = self->child_nsfds1[i];
574 		ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
575 			TH_LOG("setns failed to place us correctly into %s namespace of %d",
576 			       info->name, self->child_pid1);
577 		}
578 		TH_LOG("Managed to correctly setns to %s namespace of %d",
579 		       info->name, self->child_pid1);
580 	}
581 }
582 
583 TEST_F(current_nsset, no_foul_play)
584 {
585 	unsigned flags = 0;
586 	int i;
587 
588 	for (i = 0; i < PIDFD_NS_MAX; i++) {
589 		const struct ns_info *info = &ns_info[i];
590 
591 		if (self->child_nsfds1[i] < 0)
592 			continue;
593 
594 		flags |= info->flag;
595 		if (info->flag) /* No use logging pid_for_children. */
596 			TH_LOG("Adding %s namespace of %d to list of namespaces to attach to",
597 			       info->name, self->child_pid1);
598 	}
599 
600 	ASSERT_EQ(setns(self->child_pidfd1, flags), 0) {
601 		TH_LOG("%m - Failed to setns to namespaces of %d vid pidfd %d",
602 		       self->child_pid1, self->child_pidfd1);
603 	}
604 
605 	/*
606 	 * Can't setns to a user namespace outside of our hierarchy since we
607 	 * don't have caps in there and didn't create it. That means that under
608 	 * no circumstances should we be able to setns to any of the other
609 	 * ones since they aren't owned by our user namespace.
610 	 */
611 	for (i = 0; i < PIDFD_NS_MAX; i++) {
612 		const struct ns_info *info = &ns_info[i];
613 
614 		if (self->child_nsfds2[i] < 0 || !info->flag)
615 			continue;
616 
617 		ASSERT_NE(setns(self->child_pidfd2, info->flag), 0) {
618 			TH_LOG("Managed to setns to %s namespace of %d via pidfd %d",
619 			       info->name, self->child_pid2,
620 			       self->child_pidfd2);
621 		}
622 		TH_LOG("%m - Correctly failed to setns to %s namespace of %d via pidfd %d",
623 		       info->name, self->child_pid2,
624 		       self->child_pidfd2);
625 
626 		ASSERT_NE(setns(self->child_nsfds2[i], info->flag), 0) {
627 			TH_LOG("Managed to setns to %s namespace of %d via nsfd %d",
628 			       info->name, self->child_pid2,
629 			       self->child_nsfds2[i]);
630 		}
631 		TH_LOG("%m - Correctly failed to setns to %s namespace of %d via nsfd %d",
632 		       info->name, self->child_pid2,
633 		       self->child_nsfds2[i]);
634 	}
635 
636 	/*
637 	 * Can't setns to a user namespace outside of our hierarchy since we
638 	 * don't have caps in there and didn't create it. That means that under
639 	 * no circumstances should we be able to setns to any of the other
640 	 * ones since they aren't owned by our user namespace.
641 	 */
642 	for (i = 0; i < PIDFD_NS_MAX; i++) {
643 		const struct ns_info *info = &ns_info[i];
644 
645 		if (self->child_pidfd_derived_nsfds2[i] < 0 || !info->flag)
646 			continue;
647 
648 		ASSERT_NE(setns(self->child_pidfd_derived_nsfds2[i], info->flag), 0) {
649 			TH_LOG("Managed to setns to %s namespace of %d via nsfd %d",
650 			       info->name, self->child_pid2,
651 			       self->child_pidfd_derived_nsfds2[i]);
652 		}
653 		TH_LOG("%m - Correctly failed to setns to %s namespace of %d via nsfd %d",
654 		       info->name, self->child_pid2,
655 		       self->child_pidfd_derived_nsfds2[i]);
656 	}
657 }
658 
659 TEST(setns_einval)
660 {
661 	int fd;
662 
663 	fd = sys_memfd_create("rostock", 0);
664 	EXPECT_GT(fd, 0);
665 
666 	ASSERT_NE(setns(fd, 0), 0);
667 	EXPECT_EQ(errno, EINVAL);
668 	close(fd);
669 }
670 
671 TEST_HARNESS_MAIN
672