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