File Index
Files and directories
Sign in
FILE

pidfd_setns_test.c

File preview with syntax highlighting.

linux-6.19.14/tools/testing/selftests/pidfd/pidfd_setns_test.c C
  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
 23enum {
 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
 37const 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
 54FIXTURE(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
 75static 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
 91FIXTURE_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
323FIXTURE_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
356static 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
368static 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. */
397TEST_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. */
413TEST_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
431TEST_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
467TEST_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
503TEST_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
539TEST_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
583TEST_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
659TEST(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
671TEST_HARNESS_MAIN
~/ Read-only file preview.