| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671 |
- // SPDX-License-Identifier: GPL-2.0
- #define _GNU_SOURCE
- #include <errno.h>
- #include <fcntl.h>
- #include <limits.h>
- #include <linux/types.h>
- #include <sched.h>
- #include <signal.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <syscall.h>
- #include <sys/prctl.h>
- #include <sys/wait.h>
- #include <unistd.h>
- #include <sys/socket.h>
- #include <sys/stat.h>
- #include "pidfd.h"
- #include "kselftest_harness.h"
- enum {
- PIDFD_NS_USER,
- PIDFD_NS_MNT,
- PIDFD_NS_PID,
- PIDFD_NS_UTS,
- PIDFD_NS_IPC,
- PIDFD_NS_NET,
- PIDFD_NS_CGROUP,
- PIDFD_NS_PIDCLD,
- PIDFD_NS_TIME,
- PIDFD_NS_TIMECLD,
- PIDFD_NS_MAX
- };
- const struct ns_info {
- const char *name;
- int flag;
- unsigned int pidfd_ioctl;
- } ns_info[] = {
- [PIDFD_NS_USER] = { "user", CLONE_NEWUSER, PIDFD_GET_USER_NAMESPACE, },
- [PIDFD_NS_MNT] = { "mnt", CLONE_NEWNS, PIDFD_GET_MNT_NAMESPACE, },
- [PIDFD_NS_PID] = { "pid", CLONE_NEWPID, PIDFD_GET_PID_NAMESPACE, },
- [PIDFD_NS_UTS] = { "uts", CLONE_NEWUTS, PIDFD_GET_UTS_NAMESPACE, },
- [PIDFD_NS_IPC] = { "ipc", CLONE_NEWIPC, PIDFD_GET_IPC_NAMESPACE, },
- [PIDFD_NS_NET] = { "net", CLONE_NEWNET, PIDFD_GET_NET_NAMESPACE, },
- [PIDFD_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP, PIDFD_GET_CGROUP_NAMESPACE, },
- [PIDFD_NS_TIME] = { "time", CLONE_NEWTIME, PIDFD_GET_TIME_NAMESPACE, },
- [PIDFD_NS_PIDCLD] = { "pid_for_children", 0, PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE, },
- [PIDFD_NS_TIMECLD] = { "time_for_children", 0, PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE, },
- };
- FIXTURE(current_nsset)
- {
- pid_t pid;
- int pidfd;
- int nsfds[PIDFD_NS_MAX];
- int child_pidfd_derived_nsfds[PIDFD_NS_MAX];
- pid_t child_pid_exited;
- int child_pidfd_exited;
- pid_t child_pid1;
- int child_pidfd1;
- int child_nsfds1[PIDFD_NS_MAX];
- int child_pidfd_derived_nsfds1[PIDFD_NS_MAX];
- pid_t child_pid2;
- int child_pidfd2;
- int child_nsfds2[PIDFD_NS_MAX];
- int child_pidfd_derived_nsfds2[PIDFD_NS_MAX];
- };
- static bool switch_timens(void)
- {
- int fd, ret;
- if (unshare(CLONE_NEWTIME))
- return false;
- fd = open("/proc/self/ns/time_for_children", O_RDONLY | O_CLOEXEC);
- if (fd < 0)
- return false;
- ret = setns(fd, CLONE_NEWTIME);
- close(fd);
- return ret == 0;
- }
- FIXTURE_SETUP(current_nsset)
- {
- int i, proc_fd, ret;
- int ipc_sockets[2];
- char c;
- for (i = 0; i < PIDFD_NS_MAX; i++) {
- self->nsfds[i] = -EBADF;
- self->child_nsfds1[i] = -EBADF;
- self->child_nsfds2[i] = -EBADF;
- self->child_pidfd_derived_nsfds[i] = -EBADF;
- self->child_pidfd_derived_nsfds1[i] = -EBADF;
- self->child_pidfd_derived_nsfds2[i] = -EBADF;
- }
- proc_fd = open("/proc/self/ns", O_DIRECTORY | O_CLOEXEC);
- ASSERT_GE(proc_fd, 0) {
- TH_LOG("%m - Failed to open /proc/self/ns");
- }
- self->pid = getpid();
- self->pidfd = sys_pidfd_open(self->pid, 0);
- EXPECT_GT(self->pidfd, 0) {
- TH_LOG("%m - Failed to open pidfd for process %d", self->pid);
- }
- for (i = 0; i < PIDFD_NS_MAX; i++) {
- const struct ns_info *info = &ns_info[i];
- self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC);
- if (self->nsfds[i] < 0) {
- EXPECT_EQ(errno, ENOENT) {
- TH_LOG("%m - Failed to open %s namespace for process %d",
- info->name, self->pid);
- }
- }
- self->child_pidfd_derived_nsfds[i] = ioctl(self->pidfd, info->pidfd_ioctl, 0);
- if (self->child_pidfd_derived_nsfds[i] < 0) {
- EXPECT_EQ(errno, EOPNOTSUPP) {
- TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
- info->name, self->pid);
- }
- }
- }
- /* Create task that exits right away. */
- self->child_pid_exited = create_child(&self->child_pidfd_exited, 0);
- EXPECT_GE(self->child_pid_exited, 0);
- if (self->child_pid_exited == 0) {
- if (self->nsfds[PIDFD_NS_USER] >= 0 && unshare(CLONE_NEWUSER) < 0)
- _exit(EXIT_FAILURE);
- if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0)
- _exit(EXIT_FAILURE);
- _exit(EXIT_SUCCESS);
- }
- ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, NULL, WEXITED | WNOWAIT), 0);
- self->pidfd = sys_pidfd_open(self->pid, 0);
- EXPECT_GE(self->pidfd, 0) {
- TH_LOG("%m - Failed to open pidfd for process %d", self->pid);
- }
- ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
- EXPECT_EQ(ret, 0);
- /* Create tasks that will be stopped. */
- if (self->nsfds[PIDFD_NS_USER] >= 0 && self->nsfds[PIDFD_NS_PID] >= 0)
- self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWUSER | CLONE_NEWPID);
- else if (self->nsfds[PIDFD_NS_PID] >= 0)
- self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWPID);
- else if (self->nsfds[PIDFD_NS_USER] >= 0)
- self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWUSER);
- else
- self->child_pid1 = create_child(&self->child_pidfd1, 0);
- EXPECT_GE(self->child_pid1, 0);
- if (self->child_pid1 == 0) {
- close(ipc_sockets[0]);
- if (self->nsfds[PIDFD_NS_MNT] >= 0 && unshare(CLONE_NEWNS) < 0) {
- TH_LOG("%m - Failed to unshare mount namespace for process %d", self->pid);
- _exit(EXIT_FAILURE);
- }
- if (self->nsfds[PIDFD_NS_CGROUP] >= 0 && unshare(CLONE_NEWCGROUP) < 0) {
- TH_LOG("%m - Failed to unshare cgroup namespace for process %d", self->pid);
- _exit(EXIT_FAILURE);
- }
- if (self->nsfds[PIDFD_NS_IPC] >= 0 && unshare(CLONE_NEWIPC) < 0) {
- TH_LOG("%m - Failed to unshare ipc namespace for process %d", self->pid);
- _exit(EXIT_FAILURE);
- }
- if (self->nsfds[PIDFD_NS_UTS] >= 0 && unshare(CLONE_NEWUTS) < 0) {
- TH_LOG("%m - Failed to unshare uts namespace for process %d", self->pid);
- _exit(EXIT_FAILURE);
- }
- if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0) {
- TH_LOG("%m - Failed to unshare net namespace for process %d", self->pid);
- _exit(EXIT_FAILURE);
- }
- if (self->nsfds[PIDFD_NS_TIME] >= 0 && !switch_timens()) {
- TH_LOG("%m - Failed to unshare time namespace for process %d", self->pid);
- _exit(EXIT_FAILURE);
- }
- if (write_nointr(ipc_sockets[1], "1", 1) < 0)
- _exit(EXIT_FAILURE);
- close(ipc_sockets[1]);
- pause();
- _exit(EXIT_SUCCESS);
- }
- close(ipc_sockets[1]);
- ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
- close(ipc_sockets[0]);
- ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets);
- EXPECT_EQ(ret, 0);
- if (self->nsfds[PIDFD_NS_USER] >= 0 && self->nsfds[PIDFD_NS_PID] >= 0)
- self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWUSER | CLONE_NEWPID);
- else if (self->nsfds[PIDFD_NS_PID] >= 0)
- self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWPID);
- else if (self->nsfds[PIDFD_NS_USER] >= 0)
- self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWUSER);
- else
- self->child_pid2 = create_child(&self->child_pidfd2, 0);
- EXPECT_GE(self->child_pid2, 0);
- if (self->child_pid2 == 0) {
- close(ipc_sockets[0]);
- if (self->nsfds[PIDFD_NS_MNT] >= 0 && unshare(CLONE_NEWNS) < 0) {
- TH_LOG("%m - Failed to unshare mount namespace for process %d", self->pid);
- _exit(EXIT_FAILURE);
- }
- if (self->nsfds[PIDFD_NS_CGROUP] >= 0 && unshare(CLONE_NEWCGROUP) < 0) {
- TH_LOG("%m - Failed to unshare cgroup namespace for process %d", self->pid);
- _exit(EXIT_FAILURE);
- }
- if (self->nsfds[PIDFD_NS_IPC] >= 0 && unshare(CLONE_NEWIPC) < 0) {
- TH_LOG("%m - Failed to unshare ipc namespace for process %d", self->pid);
- _exit(EXIT_FAILURE);
- }
- if (self->nsfds[PIDFD_NS_UTS] >= 0 && unshare(CLONE_NEWUTS) < 0) {
- TH_LOG("%m - Failed to unshare uts namespace for process %d", self->pid);
- _exit(EXIT_FAILURE);
- }
- if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0) {
- TH_LOG("%m - Failed to unshare net namespace for process %d", self->pid);
- _exit(EXIT_FAILURE);
- }
- if (self->nsfds[PIDFD_NS_TIME] >= 0 && !switch_timens()) {
- TH_LOG("%m - Failed to unshare time namespace for process %d", self->pid);
- _exit(EXIT_FAILURE);
- }
- if (write_nointr(ipc_sockets[1], "1", 1) < 0)
- _exit(EXIT_FAILURE);
- close(ipc_sockets[1]);
- pause();
- _exit(EXIT_SUCCESS);
- }
- close(ipc_sockets[1]);
- ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1);
- close(ipc_sockets[0]);
- for (i = 0; i < PIDFD_NS_MAX; i++) {
- char p[100];
- const struct ns_info *info = &ns_info[i];
- self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC);
- if (self->nsfds[i] < 0) {
- EXPECT_EQ(errno, ENOENT) {
- TH_LOG("%m - Failed to open %s namespace for process %d",
- info->name, self->pid);
- }
- }
- ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s",
- self->child_pid1, info->name);
- EXPECT_GT(ret, 0);
- EXPECT_LT(ret, sizeof(p));
- self->child_nsfds1[i] = open(p, O_RDONLY | O_CLOEXEC);
- if (self->child_nsfds1[i] < 0) {
- EXPECT_EQ(errno, ENOENT) {
- TH_LOG("%m - Failed to open %s namespace for process %d",
- info->name, self->child_pid1);
- }
- }
- ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s",
- self->child_pid2, info->name);
- EXPECT_GT(ret, 0);
- EXPECT_LT(ret, sizeof(p));
- self->child_nsfds2[i] = open(p, O_RDONLY | O_CLOEXEC);
- if (self->child_nsfds2[i] < 0) {
- EXPECT_EQ(errno, ENOENT) {
- TH_LOG("%m - Failed to open %s namespace for process %d",
- info->name, self->child_pid1);
- }
- }
- self->child_pidfd_derived_nsfds1[i] = ioctl(self->child_pidfd1, info->pidfd_ioctl, 0);
- if (self->child_pidfd_derived_nsfds1[i] < 0) {
- EXPECT_EQ(errno, EOPNOTSUPP) {
- TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
- info->name, self->child_pid1);
- }
- }
- self->child_pidfd_derived_nsfds2[i] = ioctl(self->child_pidfd2, info->pidfd_ioctl, 0);
- if (self->child_pidfd_derived_nsfds2[i] < 0) {
- EXPECT_EQ(errno, EOPNOTSUPP) {
- TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d",
- info->name, self->child_pid2);
- }
- }
- }
- close(proc_fd);
- }
- FIXTURE_TEARDOWN(current_nsset)
- {
- int i;
- ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd1,
- SIGKILL, NULL, 0), 0);
- ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd2,
- SIGKILL, NULL, 0), 0);
- for (i = 0; i < PIDFD_NS_MAX; i++) {
- if (self->nsfds[i] >= 0)
- close(self->nsfds[i]);
- if (self->child_nsfds1[i] >= 0)
- close(self->child_nsfds1[i]);
- if (self->child_nsfds2[i] >= 0)
- close(self->child_nsfds2[i]);
- if (self->child_pidfd_derived_nsfds[i] >= 0)
- close(self->child_pidfd_derived_nsfds[i]);
- if (self->child_pidfd_derived_nsfds1[i] >= 0)
- close(self->child_pidfd_derived_nsfds1[i]);
- if (self->child_pidfd_derived_nsfds2[i] >= 0)
- close(self->child_pidfd_derived_nsfds2[i]);
- }
- if (self->child_pidfd1 >= 0)
- EXPECT_EQ(0, close(self->child_pidfd1));
- if (self->child_pidfd2 >= 0)
- EXPECT_EQ(0, close(self->child_pidfd2));
- ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, NULL, WEXITED), 0);
- ASSERT_EQ(sys_waitid(P_PID, self->child_pid1, NULL, WEXITED), 0);
- ASSERT_EQ(sys_waitid(P_PID, self->child_pid2, NULL, WEXITED), 0);
- }
- static int preserve_ns(const int pid, const char *ns)
- {
- int ret;
- char path[50];
- ret = snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns);
- if (ret < 0 || (size_t)ret >= sizeof(path))
- return -EIO;
- return open(path, O_RDONLY | O_CLOEXEC);
- }
- static int in_same_namespace(int ns_fd1, pid_t pid2, const char *ns)
- {
- int ns_fd2 = -EBADF;
- int ret = -1;
- struct stat ns_st1, ns_st2;
- ret = fstat(ns_fd1, &ns_st1);
- if (ret < 0)
- return -1;
- ns_fd2 = preserve_ns(pid2, ns);
- if (ns_fd2 < 0)
- return -1;
- ret = fstat(ns_fd2, &ns_st2);
- close(ns_fd2);
- if (ret < 0)
- return -1;
- /* processes are in the same namespace */
- if ((ns_st1.st_dev == ns_st2.st_dev) &&
- (ns_st1.st_ino == ns_st2.st_ino))
- return 1;
- /* processes are in different namespaces */
- return 0;
- }
- /* Test that we can't pass garbage to the kernel. */
- TEST_F(current_nsset, invalid_flags)
- {
- ASSERT_NE(setns(self->pidfd, 0), 0);
- EXPECT_EQ(errno, EINVAL);
- ASSERT_NE(setns(self->pidfd, -1), 0);
- EXPECT_EQ(errno, EINVAL);
- ASSERT_NE(setns(self->pidfd, CLONE_VM), 0);
- EXPECT_EQ(errno, EINVAL);
- ASSERT_NE(setns(self->pidfd, CLONE_NEWUSER | CLONE_VM), 0);
- EXPECT_EQ(errno, EINVAL);
- }
- /* Test that we can't attach to a task that has already exited. */
- TEST_F(current_nsset, pidfd_exited_child)
- {
- int i;
- pid_t pid;
- ASSERT_NE(setns(self->child_pidfd_exited, CLONE_NEWUSER | CLONE_NEWNET),
- 0);
- EXPECT_EQ(errno, ESRCH);
- pid = getpid();
- for (i = 0; i < PIDFD_NS_MAX; i++) {
- const struct ns_info *info = &ns_info[i];
- /* Verify that we haven't changed any namespaces. */
- if (self->nsfds[i] >= 0)
- ASSERT_EQ(in_same_namespace(self->nsfds[i], pid, info->name), 1);
- }
- }
- TEST_F(current_nsset, pidfd_incremental_setns)
- {
- int i;
- pid_t pid;
- pid = getpid();
- for (i = 0; i < PIDFD_NS_MAX; i++) {
- const struct ns_info *info = &ns_info[i];
- int nsfd;
- if (self->child_nsfds1[i] < 0)
- continue;
- if (info->flag) {
- ASSERT_EQ(setns(self->child_pidfd1, info->flag), 0) {
- TH_LOG("%m - Failed to setns to %s namespace of %d via pidfd %d",
- info->name, self->child_pid1,
- self->child_pidfd1);
- }
- }
- /* Verify that we have changed to the correct namespaces. */
- if (info->flag == CLONE_NEWPID)
- nsfd = self->nsfds[i];
- else
- nsfd = self->child_nsfds1[i];
- ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
- TH_LOG("setns failed to place us correctly into %s namespace of %d via pidfd %d",
- info->name, self->child_pid1,
- self->child_pidfd1);
- }
- TH_LOG("Managed to correctly setns to %s namespace of %d via pidfd %d",
- info->name, self->child_pid1, self->child_pidfd1);
- }
- }
- TEST_F(current_nsset, nsfd_incremental_setns)
- {
- int i;
- pid_t pid;
- pid = getpid();
- for (i = 0; i < PIDFD_NS_MAX; i++) {
- const struct ns_info *info = &ns_info[i];
- int nsfd;
- if (self->child_nsfds1[i] < 0)
- continue;
- if (info->flag) {
- ASSERT_EQ(setns(self->child_nsfds1[i], info->flag), 0) {
- TH_LOG("%m - Failed to setns to %s namespace of %d via nsfd %d",
- info->name, self->child_pid1,
- self->child_nsfds1[i]);
- }
- }
- /* Verify that we have changed to the correct namespaces. */
- if (info->flag == CLONE_NEWPID)
- nsfd = self->nsfds[i];
- else
- nsfd = self->child_nsfds1[i];
- ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
- TH_LOG("setns failed to place us correctly into %s namespace of %d via nsfd %d",
- info->name, self->child_pid1,
- self->child_nsfds1[i]);
- }
- TH_LOG("Managed to correctly setns to %s namespace of %d via nsfd %d",
- info->name, self->child_pid1, self->child_nsfds1[i]);
- }
- }
- TEST_F(current_nsset, pidfd_derived_nsfd_incremental_setns)
- {
- int i;
- pid_t pid;
- pid = getpid();
- for (i = 0; i < PIDFD_NS_MAX; i++) {
- const struct ns_info *info = &ns_info[i];
- int nsfd;
- if (self->child_pidfd_derived_nsfds1[i] < 0)
- continue;
- if (info->flag) {
- ASSERT_EQ(setns(self->child_pidfd_derived_nsfds1[i], info->flag), 0) {
- TH_LOG("%m - Failed to setns to %s namespace of %d via nsfd %d",
- info->name, self->child_pid1,
- self->child_pidfd_derived_nsfds1[i]);
- }
- }
- /* Verify that we have changed to the correct namespaces. */
- if (info->flag == CLONE_NEWPID)
- nsfd = self->child_pidfd_derived_nsfds[i];
- else
- nsfd = self->child_pidfd_derived_nsfds1[i];
- ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
- TH_LOG("setns failed to place us correctly into %s namespace of %d via nsfd %d",
- info->name, self->child_pid1,
- self->child_pidfd_derived_nsfds1[i]);
- }
- TH_LOG("Managed to correctly setns to %s namespace of %d via nsfd %d",
- info->name, self->child_pid1, self->child_pidfd_derived_nsfds1[i]);
- }
- }
- TEST_F(current_nsset, pidfd_one_shot_setns)
- {
- unsigned flags = 0;
- int i;
- pid_t pid;
- for (i = 0; i < PIDFD_NS_MAX; i++) {
- const struct ns_info *info = &ns_info[i];
- if (self->child_nsfds1[i] < 0)
- continue;
- flags |= info->flag;
- TH_LOG("Adding %s namespace of %d to list of namespaces to attach to",
- info->name, self->child_pid1);
- }
- ASSERT_EQ(setns(self->child_pidfd1, flags), 0) {
- TH_LOG("%m - Failed to setns to namespaces of %d",
- self->child_pid1);
- }
- pid = getpid();
- for (i = 0; i < PIDFD_NS_MAX; i++) {
- const struct ns_info *info = &ns_info[i];
- int nsfd;
- if (self->child_nsfds1[i] < 0)
- continue;
- /* Verify that we have changed to the correct namespaces. */
- if (info->flag == CLONE_NEWPID)
- nsfd = self->nsfds[i];
- else
- nsfd = self->child_nsfds1[i];
- ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) {
- TH_LOG("setns failed to place us correctly into %s namespace of %d",
- info->name, self->child_pid1);
- }
- TH_LOG("Managed to correctly setns to %s namespace of %d",
- info->name, self->child_pid1);
- }
- }
- TEST_F(current_nsset, no_foul_play)
- {
- unsigned flags = 0;
- int i;
- for (i = 0; i < PIDFD_NS_MAX; i++) {
- const struct ns_info *info = &ns_info[i];
- if (self->child_nsfds1[i] < 0)
- continue;
- flags |= info->flag;
- if (info->flag) /* No use logging pid_for_children. */
- TH_LOG("Adding %s namespace of %d to list of namespaces to attach to",
- info->name, self->child_pid1);
- }
- ASSERT_EQ(setns(self->child_pidfd1, flags), 0) {
- TH_LOG("%m - Failed to setns to namespaces of %d vid pidfd %d",
- self->child_pid1, self->child_pidfd1);
- }
- /*
- * Can't setns to a user namespace outside of our hierarchy since we
- * don't have caps in there and didn't create it. That means that under
- * no circumstances should we be able to setns to any of the other
- * ones since they aren't owned by our user namespace.
- */
- for (i = 0; i < PIDFD_NS_MAX; i++) {
- const struct ns_info *info = &ns_info[i];
- if (self->child_nsfds2[i] < 0 || !info->flag)
- continue;
- ASSERT_NE(setns(self->child_pidfd2, info->flag), 0) {
- TH_LOG("Managed to setns to %s namespace of %d via pidfd %d",
- info->name, self->child_pid2,
- self->child_pidfd2);
- }
- TH_LOG("%m - Correctly failed to setns to %s namespace of %d via pidfd %d",
- info->name, self->child_pid2,
- self->child_pidfd2);
- ASSERT_NE(setns(self->child_nsfds2[i], info->flag), 0) {
- TH_LOG("Managed to setns to %s namespace of %d via nsfd %d",
- info->name, self->child_pid2,
- self->child_nsfds2[i]);
- }
- TH_LOG("%m - Correctly failed to setns to %s namespace of %d via nsfd %d",
- info->name, self->child_pid2,
- self->child_nsfds2[i]);
- }
- /*
- * Can't setns to a user namespace outside of our hierarchy since we
- * don't have caps in there and didn't create it. That means that under
- * no circumstances should we be able to setns to any of the other
- * ones since they aren't owned by our user namespace.
- */
- for (i = 0; i < PIDFD_NS_MAX; i++) {
- const struct ns_info *info = &ns_info[i];
- if (self->child_pidfd_derived_nsfds2[i] < 0 || !info->flag)
- continue;
- ASSERT_NE(setns(self->child_pidfd_derived_nsfds2[i], info->flag), 0) {
- TH_LOG("Managed to setns to %s namespace of %d via nsfd %d",
- info->name, self->child_pid2,
- self->child_pidfd_derived_nsfds2[i]);
- }
- TH_LOG("%m - Correctly failed to setns to %s namespace of %d via nsfd %d",
- info->name, self->child_pid2,
- self->child_pidfd_derived_nsfds2[i]);
- }
- }
- TEST(setns_einval)
- {
- int fd;
- fd = sys_memfd_create("rostock", 0);
- EXPECT_GT(fd, 0);
- ASSERT_NE(setns(fd, 0), 0);
- EXPECT_EQ(errno, EINVAL);
- close(fd);
- }
- TEST_HARNESS_MAIN
|