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