brintos

brintos / linux-shallow public Read only

0
0
Text · 21.0 KiB · 7c2a434 Raw
756 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#define _GNU_SOURCE4#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_MAGIC26#define PIDFS_IOCTL_MAGIC 0xFF27#endif28 29#ifndef PIDFD_GET_CGROUP_NAMESPACE30#define PIDFD_GET_CGROUP_NAMESPACE            _IO(PIDFS_IOCTL_MAGIC, 1)31#endif32 33#ifndef PIDFD_GET_IPC_NAMESPACE34#define PIDFD_GET_IPC_NAMESPACE               _IO(PIDFS_IOCTL_MAGIC, 2)35#endif36 37#ifndef PIDFD_GET_MNT_NAMESPACE38#define PIDFD_GET_MNT_NAMESPACE               _IO(PIDFS_IOCTL_MAGIC, 3)39#endif40 41#ifndef PIDFD_GET_NET_NAMESPACE42#define PIDFD_GET_NET_NAMESPACE               _IO(PIDFS_IOCTL_MAGIC, 4)43#endif44 45#ifndef PIDFD_GET_PID_NAMESPACE46#define PIDFD_GET_PID_NAMESPACE               _IO(PIDFS_IOCTL_MAGIC, 5)47#endif48 49#ifndef PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE50#define PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE  _IO(PIDFS_IOCTL_MAGIC, 6)51#endif52 53#ifndef PIDFD_GET_TIME_NAMESPACE54#define PIDFD_GET_TIME_NAMESPACE              _IO(PIDFS_IOCTL_MAGIC, 7)55#endif56 57#ifndef PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE58#define PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 8)59#endif60 61#ifndef PIDFD_GET_USER_NAMESPACE62#define PIDFD_GET_USER_NAMESPACE              _IO(PIDFS_IOCTL_MAGIC, 9)63#endif64 65#ifndef PIDFD_GET_UTS_NAMESPACE66#define PIDFD_GET_UTS_NAMESPACE               _IO(PIDFS_IOCTL_MAGIC, 10)67#endif68 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_MAX81};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	else250		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	else304		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		else540			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		else576			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		else612			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		else657			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 we691	 * don't have caps in there and didn't create it. That means that under692	 * no circumstances should we be able to setns to any of the other693	 * 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 we722	 * don't have caps in there and didn't create it. That means that under723	 * no circumstances should we be able to setns to any of the other724	 * 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_MAIN756