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 "../clone3/clone3_selftests.h" 23 #include "../kselftest_harness.h" 24 25 #ifndef PIDFS_IOCTL_MAGIC 26 #define PIDFS_IOCTL_MAGIC 0xFF 27 #endif 28 29 #ifndef PIDFD_GET_CGROUP_NAMESPACE 30 #define PIDFD_GET_CGROUP_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 1) 31 #endif 32 33 #ifndef PIDFD_GET_IPC_NAMESPACE 34 #define PIDFD_GET_IPC_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 2) 35 #endif 36 37 #ifndef PIDFD_GET_MNT_NAMESPACE 38 #define PIDFD_GET_MNT_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 3) 39 #endif 40 41 #ifndef PIDFD_GET_NET_NAMESPACE 42 #define PIDFD_GET_NET_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 4) 43 #endif 44 45 #ifndef PIDFD_GET_PID_NAMESPACE 46 #define PIDFD_GET_PID_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 5) 47 #endif 48 49 #ifndef PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE 50 #define PIDFD_GET_PID_FOR_CHILDREN_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 6) 51 #endif 52 53 #ifndef PIDFD_GET_TIME_NAMESPACE 54 #define PIDFD_GET_TIME_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 7) 55 #endif 56 57 #ifndef PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE 58 #define PIDFD_GET_TIME_FOR_CHILDREN_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 8) 59 #endif 60 61 #ifndef PIDFD_GET_USER_NAMESPACE 62 #define PIDFD_GET_USER_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 9) 63 #endif 64 65 #ifndef PIDFD_GET_UTS_NAMESPACE 66 #define PIDFD_GET_UTS_NAMESPACE _IO(PIDFS_IOCTL_MAGIC, 10) 67 #endif 68 69 enum { 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_MAX 81 }; 82 83 const 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 100 FIXTURE(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 121 static int sys_waitid(int which, pid_t pid, int options) 122 { 123 return syscall(__NR_waitid, which, pid, NULL, options, NULL); 124 } 125 126 pid_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 137 static 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 153 static 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 164 static 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 175 FIXTURE_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 else 250 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 else 304 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 407 FIXTURE_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 440 static 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 452 static 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. */ 481 TEST_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. */ 497 TEST_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 515 TEST_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 else 540 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 551 TEST_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 else 576 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 587 TEST_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 else 612 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 623 TEST_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 else 657 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 667 TEST_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 we 691 * don't have caps in there and didn't create it. That means that under 692 * no circumstances should we be able to setns to any of the other 693 * 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 we 722 * don't have caps in there and didn't create it. That means that under 723 * no circumstances should we be able to setns to any of the other 724 * 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 743 TEST(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 755 TEST_HARNESS_MAIN 756
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.