Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  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
 69enum {
 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
 83const 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
100FIXTURE(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
121static int sys_waitid(int which, pid_t pid, int options)
122{
123	return syscall(__NR_waitid, which, pid, NULL, options, NULL);
124}
125
126pid_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
137static 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
153static 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
164static 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
175FIXTURE_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
407FIXTURE_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
440static 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
452static 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. */
481TEST_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. */
497TEST_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
515TEST_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
551TEST_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
587TEST_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
623TEST_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
667TEST_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
743TEST(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
755TEST_HARNESS_MAIN