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 #include <linux/ioctl.h> 20 21 #include "pidfd.h" 22 #include "../kselftest_harness.h" 23 24 #ifndef PIDFS_IOCTL_MAGIC 25 #define PIDFS_IOCTL_MAGIC 0xFF 26 #endif 27 28 #ifndef PIDFD_GET_CGROUP_NAMESPACE 29 #define PIDFD_GET_CGROUP_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 1) 30 #endif 31 32 #ifndef PIDFD_GET_IPC_NAMESPACE 33 #define PIDFD_GET_IPC_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 2) 34 #endif 35 36 #ifndef PIDFD_GET_MNT_NAMESPACE 37 #define PIDFD_GET_MNT_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 3) 38 #endif 39 40 #ifndef PIDFD_GET_NET_NAMESPACE 41 #define PIDFD_GET_NET_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 4) 42 #endif 43 44 #ifndef PIDFD_GET_PID_NAMESPACE 45 #define PIDFD_GET_PID_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 5) 46 #endif 47 48 #ifndef PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE 49 #define PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 6) 50 #endif 51 52 #ifndef PIDFD_GET_TIME_NAMESPACE 53 #define PIDFD_GET_TIME_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 7) 54 #endif 55 56 #ifndef PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE 57 #define PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 8) 58 #endif 59 60 #ifndef PIDFD_GET_USER_NAMESPACE 61 #define PIDFD_GET_USER_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 9) 62 #endif 63 64 #ifndef PIDFD_GET_UTS_NAMESPACE 65 #define PIDFD_GET_UTS_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 10) 66 #endif 67 68 enum { 69 PIDFD_NS_USER, 70 PIDFD_NS_MNT, 71 PIDFD_NS_PID, 72 PIDFD_NS_UTS, 73 PIDFD_NS_IPC, 74 PIDFD_NS_NET, 75 PIDFD_NS_CGROUP, 76 PIDFD_NS_PIDCLD, 77 PIDFD_NS_TIME, 78 PIDFD_NS_TIMECLD, 79 PIDFD_NS_MAX 80 }; 81 82 const struct ns_info { 83 const char *name; 84 int flag; 85 unsigned int pidfd_ioctl; 86 } ns_info[] = { 87 [PIDFD_NS_USER] = { "user", CLONE_NEWUSER, PIDFD_GET_USER_NAMESPACE, }, 88 [PIDFD_NS_MNT] = { "mnt", CLONE_NEWNS, PIDFD_GET_MNT_NAMESPACE, }, 89 [PIDFD_NS_PID] = { "pid", CLONE_NEWPID, PIDFD_GET_PID_NAMESPACE, }, 90 [PIDFD_NS_UTS] = { "uts", CLONE_NEWUTS, PIDFD_GET_UTS_NAMESPACE, }, 91 [PIDFD_NS_IPC] = { "ipc", CLONE_NEWIPC, PIDFD_GET_IPC_NAMESPACE, }, 92 [PIDFD_NS_NET] = { "net", CLONE_NEWNET, PIDFD_GET_NET_NAMESPACE, }, 93 [PIDFD_NS_CGROUP] = { "cgroup", CLONE_NEWCGROUP, PIDFD_GET_CGROUP_NAMESPACE, }, 94 [PIDFD_NS_TIME] = { "time", CLONE_NEWTIME, PIDFD_GET_TIME_NAMESPACE, }, 95 [PIDFD_NS_PIDCLD] = { "pid_for_children", 0, PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE, }, 96 [PIDFD_NS_TIMECLD] = { "time_for_children", 0, PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE, }, 97 }; 98 99 FIXTURE(current_nsset) 100 { 101 pid_t pid; 102 int pidfd; 103 int nsfds[PIDFD_NS_MAX]; 104 int child_pidfd_derived_nsfds[PIDFD_NS_MAX]; 105 106 pid_t child_pid_exited; 107 int child_pidfd_exited; 108 109 pid_t child_pid1; 110 int child_pidfd1; 111 int child_nsfds1[PIDFD_NS_MAX]; 112 int child_pidfd_derived_nsfds1[PIDFD_NS_MAX]; 113 114 pid_t child_pid2; 115 int child_pidfd2; 116 int child_nsfds2[PIDFD_NS_MAX]; 117 int child_pidfd_derived_nsfds2[PIDFD_NS_MAX]; 118 }; 119 120 static bool switch_timens(void) 121 { 122 int fd, ret; 123 124 if (unshare(CLONE_NEWTIME)) 125 return false; 126 127 fd = open("/proc/self/ns/time_for_children", O_RDONLY | O_CLOEXEC); 128 if (fd < 0) 129 return false; 130 131 ret = setns(fd, CLONE_NEWTIME); 132 close(fd); 133 return ret == 0; 134 } 135 136 FIXTURE_SETUP(current_nsset) 137 { 138 int i, proc_fd, ret; 139 int ipc_sockets[2]; 140 char c; 141 142 for (i = 0; i < PIDFD_NS_MAX; i++) { 143 self->nsfds[i] = -EBADF; 144 self->child_nsfds1[i] = -EBADF; 145 self->child_nsfds2[i] = -EBADF; 146 self->child_pidfd_derived_nsfds[i] = -EBADF; 147 self->child_pidfd_derived_nsfds1[i] = -EBADF; 148 self->child_pidfd_derived_nsfds2[i] = -EBADF; 149 } 150 151 proc_fd = open("/proc/self/ns", O_DIRECTORY | O_CLOEXEC); 152 ASSERT_GE(proc_fd, 0) { 153 TH_LOG("%m - Failed to open /proc/self/ns"); 154 } 155 156 self->pid = getpid(); 157 self->pidfd = sys_pidfd_open(self->pid, 0); 158 EXPECT_GT(self->pidfd, 0) { 159 TH_LOG("%m - Failed to open pidfd for process %d", self->pid); 160 } 161 162 for (i = 0; i < PIDFD_NS_MAX; i++) { 163 const struct ns_info *info = &ns_info[i]; 164 self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC); 165 if (self->nsfds[i] < 0) { 166 EXPECT_EQ(errno, ENOENT) { 167 TH_LOG("%m - Failed to open %s namespace for process %d", 168 info->name, self->pid); 169 } 170 } 171 172 self->child_pidfd_derived_nsfds[i] = ioctl(self->pidfd, info->pidfd_ioctl, 0); 173 if (self->child_pidfd_derived_nsfds[i] < 0) { 174 EXPECT_EQ(errno, EOPNOTSUPP) { 175 TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d", 176 info->name, self->pid); 177 } 178 } 179 } 180 181 /* Create task that exits right away. */ 182 self->child_pid_exited = create_child(&self->child_pidfd_exited, 0); 183 EXPECT_GE(self->child_pid_exited, 0); 184 185 if (self->child_pid_exited == 0) { 186 if (self->nsfds[PIDFD_NS_USER] >= 0 && unshare(CLONE_NEWUSER) < 0) 187 _exit(EXIT_FAILURE); 188 if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0) 189 _exit(EXIT_FAILURE); 190 _exit(EXIT_SUCCESS); 191 } 192 193 ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, NULL, WEXITED | WNOWAIT), 0); 194 195 self->pidfd = sys_pidfd_open(self->pid, 0); 196 EXPECT_GE(self->pidfd, 0) { 197 TH_LOG("%m - Failed to open pidfd for process %d", self->pid); 198 } 199 200 ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 201 EXPECT_EQ(ret, 0); 202 203 /* Create tasks that will be stopped. */ 204 if (self->nsfds[PIDFD_NS_USER] >= 0 && self->nsfds[PIDFD_NS_PID] >= 0) 205 self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWUSER | CLONE_NEWPID); 206 else if (self->nsfds[PIDFD_NS_PID] >= 0) 207 self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWPID); 208 else if (self->nsfds[PIDFD_NS_USER] >= 0) 209 self->child_pid1 = create_child(&self->child_pidfd1, CLONE_NEWUSER); 210 else 211 self->child_pid1 = create_child(&self->child_pidfd1, 0); 212 EXPECT_GE(self->child_pid1, 0); 213 214 if (self->child_pid1 == 0) { 215 close(ipc_sockets[0]); 216 217 if (self->nsfds[PIDFD_NS_MNT] >= 0 && unshare(CLONE_NEWNS) < 0) { 218 TH_LOG("%m - Failed to unshare mount namespace for process %d", self->pid); 219 _exit(EXIT_FAILURE); 220 } 221 if (self->nsfds[PIDFD_NS_CGROUP] >= 0 && unshare(CLONE_NEWCGROUP) < 0) { 222 TH_LOG("%m - Failed to unshare cgroup namespace for process %d", self->pid); 223 _exit(EXIT_FAILURE); 224 } 225 if (self->nsfds[PIDFD_NS_IPC] >= 0 && unshare(CLONE_NEWIPC) < 0) { 226 TH_LOG("%m - Failed to unshare ipc namespace for process %d", self->pid); 227 _exit(EXIT_FAILURE); 228 } 229 if (self->nsfds[PIDFD_NS_UTS] >= 0 && unshare(CLONE_NEWUTS) < 0) { 230 TH_LOG("%m - Failed to unshare uts namespace for process %d", self->pid); 231 _exit(EXIT_FAILURE); 232 } 233 if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0) { 234 TH_LOG("%m - Failed to unshare net namespace for process %d", self->pid); 235 _exit(EXIT_FAILURE); 236 } 237 if (self->nsfds[PIDFD_NS_TIME] >= 0 && !switch_timens()) { 238 TH_LOG("%m - Failed to unshare time namespace for process %d", self->pid); 239 _exit(EXIT_FAILURE); 240 } 241 242 if (write_nointr(ipc_sockets[1], "1", 1) < 0) 243 _exit(EXIT_FAILURE); 244 245 close(ipc_sockets[1]); 246 247 pause(); 248 _exit(EXIT_SUCCESS); 249 } 250 251 close(ipc_sockets[1]); 252 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 253 close(ipc_sockets[0]); 254 255 ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, ipc_sockets); 256 EXPECT_EQ(ret, 0); 257 258 if (self->nsfds[PIDFD_NS_USER] >= 0 && self->nsfds[PIDFD_NS_PID] >= 0) 259 self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWUSER | CLONE_NEWPID); 260 else if (self->nsfds[PIDFD_NS_PID] >= 0) 261 self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWPID); 262 else if (self->nsfds[PIDFD_NS_USER] >= 0) 263 self->child_pid2 = create_child(&self->child_pidfd2, CLONE_NEWUSER); 264 else 265 self->child_pid2 = create_child(&self->child_pidfd2, 0); 266 EXPECT_GE(self->child_pid2, 0); 267 268 if (self->child_pid2 == 0) { 269 close(ipc_sockets[0]); 270 271 if (self->nsfds[PIDFD_NS_MNT] >= 0 && unshare(CLONE_NEWNS) < 0) { 272 TH_LOG("%m - Failed to unshare mount namespace for process %d", self->pid); 273 _exit(EXIT_FAILURE); 274 } 275 if (self->nsfds[PIDFD_NS_CGROUP] >= 0 && unshare(CLONE_NEWCGROUP) < 0) { 276 TH_LOG("%m - Failed to unshare cgroup namespace for process %d", self->pid); 277 _exit(EXIT_FAILURE); 278 } 279 if (self->nsfds[PIDFD_NS_IPC] >= 0 && unshare(CLONE_NEWIPC) < 0) { 280 TH_LOG("%m - Failed to unshare ipc namespace for process %d", self->pid); 281 _exit(EXIT_FAILURE); 282 } 283 if (self->nsfds[PIDFD_NS_UTS] >= 0 && unshare(CLONE_NEWUTS) < 0) { 284 TH_LOG("%m - Failed to unshare uts namespace for process %d", self->pid); 285 _exit(EXIT_FAILURE); 286 } 287 if (self->nsfds[PIDFD_NS_NET] >= 0 && unshare(CLONE_NEWNET) < 0) { 288 TH_LOG("%m - Failed to unshare net namespace for process %d", self->pid); 289 _exit(EXIT_FAILURE); 290 } 291 if (self->nsfds[PIDFD_NS_TIME] >= 0 && !switch_timens()) { 292 TH_LOG("%m - Failed to unshare time namespace for process %d", self->pid); 293 _exit(EXIT_FAILURE); 294 } 295 296 if (write_nointr(ipc_sockets[1], "1", 1) < 0) 297 _exit(EXIT_FAILURE); 298 299 close(ipc_sockets[1]); 300 301 pause(); 302 _exit(EXIT_SUCCESS); 303 } 304 305 close(ipc_sockets[1]); 306 ASSERT_EQ(read_nointr(ipc_sockets[0], &c, 1), 1); 307 close(ipc_sockets[0]); 308 309 for (i = 0; i < PIDFD_NS_MAX; i++) { 310 char p[100]; 311 312 const struct ns_info *info = &ns_info[i]; 313 314 self->nsfds[i] = openat(proc_fd, info->name, O_RDONLY | O_CLOEXEC); 315 if (self->nsfds[i] < 0) { 316 EXPECT_EQ(errno, ENOENT) { 317 TH_LOG("%m - Failed to open %s namespace for process %d", 318 info->name, self->pid); 319 } 320 } 321 322 ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s", 323 self->child_pid1, info->name); 324 EXPECT_GT(ret, 0); 325 EXPECT_LT(ret, sizeof(p)); 326 327 self->child_nsfds1[i] = open(p, O_RDONLY | O_CLOEXEC); 328 if (self->child_nsfds1[i] < 0) { 329 EXPECT_EQ(errno, ENOENT) { 330 TH_LOG("%m - Failed to open %s namespace for process %d", 331 info->name, self->child_pid1); 332 } 333 } 334 335 ret = snprintf(p, sizeof(p), "/proc/%d/ns/%s", 336 self->child_pid2, info->name); 337 EXPECT_GT(ret, 0); 338 EXPECT_LT(ret, sizeof(p)); 339 340 self->child_nsfds2[i] = open(p, O_RDONLY | O_CLOEXEC); 341 if (self->child_nsfds2[i] < 0) { 342 EXPECT_EQ(errno, ENOENT) { 343 TH_LOG("%m - Failed to open %s namespace for process %d", 344 info->name, self->child_pid1); 345 } 346 } 347 348 self->child_pidfd_derived_nsfds1[i] = ioctl(self->child_pidfd1, info->pidfd_ioctl, 0); 349 if (self->child_pidfd_derived_nsfds1[i] < 0) { 350 EXPECT_EQ(errno, EOPNOTSUPP) { 351 TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d", 352 info->name, self->child_pid1); 353 } 354 } 355 356 self->child_pidfd_derived_nsfds2[i] = ioctl(self->child_pidfd2, info->pidfd_ioctl, 0); 357 if (self->child_pidfd_derived_nsfds2[i] < 0) { 358 EXPECT_EQ(errno, EOPNOTSUPP) { 359 TH_LOG("%m - Failed to derive %s namespace from pidfd of process %d", 360 info->name, self->child_pid2); 361 } 362 } 363 } 364 365 close(proc_fd); 366 } 367 368 FIXTURE_TEARDOWN(current_nsset) 369 { 370 int i; 371 372 ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd1, 373 SIGKILL, NULL, 0), 0); 374 ASSERT_EQ(sys_pidfd_send_signal(self->child_pidfd2, 375 SIGKILL, NULL, 0), 0); 376 377 for (i = 0; i < PIDFD_NS_MAX; i++) { 378 if (self->nsfds[i] >= 0) 379 close(self->nsfds[i]); 380 if (self->child_nsfds1[i] >= 0) 381 close(self->child_nsfds1[i]); 382 if (self->child_nsfds2[i] >= 0) 383 close(self->child_nsfds2[i]); 384 if (self->child_pidfd_derived_nsfds[i] >= 0) 385 close(self->child_pidfd_derived_nsfds[i]); 386 if (self->child_pidfd_derived_nsfds1[i] >= 0) 387 close(self->child_pidfd_derived_nsfds1[i]); 388 if (self->child_pidfd_derived_nsfds2[i] >= 0) 389 close(self->child_pidfd_derived_nsfds2[i]); 390 } 391 392 if (self->child_pidfd1 >= 0) 393 EXPECT_EQ(0, close(self->child_pidfd1)); 394 if (self->child_pidfd2 >= 0) 395 EXPECT_EQ(0, close(self->child_pidfd2)); 396 ASSERT_EQ(sys_waitid(P_PID, self->child_pid_exited, NULL, WEXITED), 0); 397 ASSERT_EQ(sys_waitid(P_PID, self->child_pid1, NULL, WEXITED), 0); 398 ASSERT_EQ(sys_waitid(P_PID, self->child_pid2, NULL, WEXITED), 0); 399 } 400 401 static int preserve_ns(const int pid, const char *ns) 402 { 403 int ret; 404 char path[50]; 405 406 ret = snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns); 407 if (ret < 0 || (size_t)ret >= sizeof(path)) 408 return -EIO; 409 410 return open(path, O_RDONLY | O_CLOEXEC); 411 } 412 413 static int in_same_namespace(int ns_fd1, pid_t pid2, const char *ns) 414 { 415 int ns_fd2 = -EBADF; 416 int ret = -1; 417 struct stat ns_st1, ns_st2; 418 419 ret = fstat(ns_fd1, &ns_st1); 420 if (ret < 0) 421 return -1; 422 423 ns_fd2 = preserve_ns(pid2, ns); 424 if (ns_fd2 < 0) 425 return -1; 426 427 ret = fstat(ns_fd2, &ns_st2); 428 close(ns_fd2); 429 if (ret < 0) 430 return -1; 431 432 /* processes are in the same namespace */ 433 if ((ns_st1.st_dev == ns_st2.st_dev) && 434 (ns_st1.st_ino == ns_st2.st_ino)) 435 return 1; 436 437 /* processes are in different namespaces */ 438 return 0; 439 } 440 441 /* Test that we can't pass garbage to the kernel. */ 442 TEST_F(current_nsset, invalid_flags) 443 { 444 ASSERT_NE(setns(self->pidfd, 0), 0); 445 EXPECT_EQ(errno, EINVAL); 446 447 ASSERT_NE(setns(self->pidfd, -1), 0); 448 EXPECT_EQ(errno, EINVAL); 449 450 ASSERT_NE(setns(self->pidfd, CLONE_VM), 0); 451 EXPECT_EQ(errno, EINVAL); 452 453 ASSERT_NE(setns(self->pidfd, CLONE_NEWUSER | CLONE_VM), 0); 454 EXPECT_EQ(errno, EINVAL); 455 } 456 457 /* Test that we can't attach to a task that has already exited. */ 458 TEST_F(current_nsset, pidfd_exited_child) 459 { 460 int i; 461 pid_t pid; 462 463 ASSERT_NE(setns(self->child_pidfd_exited, CLONE_NEWUSER | CLONE_NEWNET), 464 0); 465 EXPECT_EQ(errno, ESRCH); 466 467 pid = getpid(); 468 for (i = 0; i < PIDFD_NS_MAX; i++) { 469 const struct ns_info *info = &ns_info[i]; 470 /* Verify that we haven't changed any namespaces. */ 471 if (self->nsfds[i] >= 0) 472 ASSERT_EQ(in_same_namespace(self->nsfds[i], pid, info->name), 1); 473 } 474 } 475 476 TEST_F(current_nsset, pidfd_incremental_setns) 477 { 478 int i; 479 pid_t pid; 480 481 pid = getpid(); 482 for (i = 0; i < PIDFD_NS_MAX; i++) { 483 const struct ns_info *info = &ns_info[i]; 484 int nsfd; 485 486 if (self->child_nsfds1[i] < 0) 487 continue; 488 489 if (info->flag) { 490 ASSERT_EQ(setns(self->child_pidfd1, info->flag), 0) { 491 TH_LOG("%m - Failed to setns to %s namespace of %d via pidfd %d", 492 info->name, self->child_pid1, 493 self->child_pidfd1); 494 } 495 } 496 497 /* Verify that we have changed to the correct namespaces. */ 498 if (info->flag == CLONE_NEWPID) 499 nsfd = self->nsfds[i]; 500 else 501 nsfd = self->child_nsfds1[i]; 502 ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) { 503 TH_LOG("setns failed to place us correctly into %s namespace of %d via pidfd %d", 504 info->name, self->child_pid1, 505 self->child_pidfd1); 506 } 507 TH_LOG("Managed to correctly setns to %s namespace of %d via pidfd %d", 508 info->name, self->child_pid1, self->child_pidfd1); 509 } 510 } 511 512 TEST_F(current_nsset, nsfd_incremental_setns) 513 { 514 int i; 515 pid_t pid; 516 517 pid = getpid(); 518 for (i = 0; i < PIDFD_NS_MAX; i++) { 519 const struct ns_info *info = &ns_info[i]; 520 int nsfd; 521 522 if (self->child_nsfds1[i] < 0) 523 continue; 524 525 if (info->flag) { 526 ASSERT_EQ(setns(self->child_nsfds1[i], info->flag), 0) { 527 TH_LOG("%m - Failed to setns to %s namespace of %d via nsfd %d", 528 info->name, self->child_pid1, 529 self->child_nsfds1[i]); 530 } 531 } 532 533 /* Verify that we have changed to the correct namespaces. */ 534 if (info->flag == CLONE_NEWPID) 535 nsfd = self->nsfds[i]; 536 else 537 nsfd = self->child_nsfds1[i]; 538 ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) { 539 TH_LOG("setns failed to place us correctly into %s namespace of %d via nsfd %d", 540 info->name, self->child_pid1, 541 self->child_nsfds1[i]); 542 } 543 TH_LOG("Managed to correctly setns to %s namespace of %d via nsfd %d", 544 info->name, self->child_pid1, self->child_nsfds1[i]); 545 } 546 } 547 548 TEST_F(current_nsset, pidfd_derived_nsfd_incremental_setns) 549 { 550 int i; 551 pid_t pid; 552 553 pid = getpid(); 554 for (i = 0; i < PIDFD_NS_MAX; i++) { 555 const struct ns_info *info = &ns_info[i]; 556 int nsfd; 557 558 if (self->child_pidfd_derived_nsfds1[i] < 0) 559 continue; 560 561 if (info->flag) { 562 ASSERT_EQ(setns(self->child_pidfd_derived_nsfds1[i], info->flag), 0) { 563 TH_LOG("%m - Failed to setns to %s namespace of %d via nsfd %d", 564 info->name, self->child_pid1, 565 self->child_pidfd_derived_nsfds1[i]); 566 } 567 } 568 569 /* Verify that we have changed to the correct namespaces. */ 570 if (info->flag == CLONE_NEWPID) 571 nsfd = self->child_pidfd_derived_nsfds[i]; 572 else 573 nsfd = self->child_pidfd_derived_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 via nsfd %d", 576 info->name, self->child_pid1, 577 self->child_pidfd_derived_nsfds1[i]); 578 } 579 TH_LOG("Managed to correctly setns to %s namespace of %d via nsfd %d", 580 info->name, self->child_pid1, self->child_pidfd_derived_nsfds1[i]); 581 } 582 } 583 584 TEST_F(current_nsset, pidfd_one_shot_setns) 585 { 586 unsigned flags = 0; 587 int i; 588 pid_t pid; 589 590 for (i = 0; i < PIDFD_NS_MAX; i++) { 591 const struct ns_info *info = &ns_info[i]; 592 593 if (self->child_nsfds1[i] < 0) 594 continue; 595 596 flags |= info->flag; 597 TH_LOG("Adding %s namespace of %d to list of namespaces to attach to", 598 info->name, self->child_pid1); 599 } 600 601 ASSERT_EQ(setns(self->child_pidfd1, flags), 0) { 602 TH_LOG("%m - Failed to setns to namespaces of %d", 603 self->child_pid1); 604 } 605 606 pid = getpid(); 607 for (i = 0; i < PIDFD_NS_MAX; i++) { 608 const struct ns_info *info = &ns_info[i]; 609 int nsfd; 610 611 if (self->child_nsfds1[i] < 0) 612 continue; 613 614 /* Verify that we have changed to the correct namespaces. */ 615 if (info->flag == CLONE_NEWPID) 616 nsfd = self->nsfds[i]; 617 else 618 nsfd = self->child_nsfds1[i]; 619 ASSERT_EQ(in_same_namespace(nsfd, pid, info->name), 1) { 620 TH_LOG("setns failed to place us correctly into %s namespace of %d", 621 info->name, self->child_pid1); 622 } 623 TH_LOG("Managed to correctly setns to %s namespace of %d", 624 info->name, self->child_pid1); 625 } 626 } 627 628 TEST_F(current_nsset, no_foul_play) 629 { 630 unsigned flags = 0; 631 int i; 632 633 for (i = 0; i < PIDFD_NS_MAX; i++) { 634 const struct ns_info *info = &ns_info[i]; 635 636 if (self->child_nsfds1[i] < 0) 637 continue; 638 639 flags |= info->flag; 640 if (info->flag) /* No use logging pid_for_children. */ 641 TH_LOG("Adding %s namespace of %d to list of namespaces to attach to", 642 info->name, self->child_pid1); 643 } 644 645 ASSERT_EQ(setns(self->child_pidfd1, flags), 0) { 646 TH_LOG("%m - Failed to setns to namespaces of %d vid pidfd %d", 647 self->child_pid1, self->child_pidfd1); 648 } 649 650 /* 651 * Can't setns to a user namespace outside of our hierarchy since we 652 * don't have caps in there and didn't create it. That means that under 653 * no circumstances should we be able to setns to any of the other 654 * ones since they aren't owned by our user namespace. 655 */ 656 for (i = 0; i < PIDFD_NS_MAX; i++) { 657 const struct ns_info *info = &ns_info[i]; 658 659 if (self->child_nsfds2[i] < 0 || !info->flag) 660 continue; 661 662 ASSERT_NE(setns(self->child_pidfd2, info->flag), 0) { 663 TH_LOG("Managed to setns to %s namespace of %d via pidfd %d", 664 info->name, self->child_pid2, 665 self->child_pidfd2); 666 } 667 TH_LOG("%m - Correctly failed to setns to %s namespace of %d via pidfd %d", 668 info->name, self->child_pid2, 669 self->child_pidfd2); 670 671 ASSERT_NE(setns(self->child_nsfds2[i], info->flag), 0) { 672 TH_LOG("Managed to setns to %s namespace of %d via nsfd %d", 673 info->name, self->child_pid2, 674 self->child_nsfds2[i]); 675 } 676 TH_LOG("%m - Correctly failed to setns to %s namespace of %d via nsfd %d", 677 info->name, self->child_pid2, 678 self->child_nsfds2[i]); 679 } 680 681 /* 682 * Can't setns to a user namespace outside of our hierarchy since we 683 * don't have caps in there and didn't create it. That means that under 684 * no circumstances should we be able to setns to any of the other 685 * ones since they aren't owned by our user namespace. 686 */ 687 for (i = 0; i < PIDFD_NS_MAX; i++) { 688 const struct ns_info *info = &ns_info[i]; 689 690 if (self->child_pidfd_derived_nsfds2[i] < 0 || !info->flag) 691 continue; 692 693 ASSERT_NE(setns(self->child_pidfd_derived_nsfds2[i], info->flag), 0) { 694 TH_LOG("Managed to setns to %s namespace of %d via nsfd %d", 695 info->name, self->child_pid2, 696 self->child_pidfd_derived_nsfds2[i]); 697 } 698 TH_LOG("%m - Correctly failed to setns to %s namespace of %d via nsfd %d", 699 info->name, self->child_pid2, 700 self->child_pidfd_derived_nsfds2[i]); 701 } 702 } 703 704 TEST(setns_einval) 705 { 706 int fd; 707 708 fd = sys_memfd_create("rostock", 0); 709 EXPECT_GT(fd, 0); 710 711 ASSERT_NE(setns(fd, 0), 0); 712 EXPECT_EQ(errno, EINVAL); 713 close(fd); 714 } 715 716 TEST_HARNESS_MAIN 717