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