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);
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);
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]);
}
staticint preserve_ns(constint pid, constchar *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);
}
staticint in_same_namespace(int ns_fd1, pid_t pid2, constchar *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);
pid = getpid(); for (i = 0; i < PIDFD_NS_MAX; i++) { conststruct 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++) { conststruct 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++) { conststruct 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++) { conststruct 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]);
}
}
for (i = 0; i < PIDFD_NS_MAX; i++) { conststruct 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++) { conststruct 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++) { conststruct 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++) { conststruct 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++) { conststruct 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]);
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.