Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/namespaces: fifth listns() permission test

Test that CAP_SYS_ADMIN in parent user namespace allows seeing
child user namespace's owned namespaces.

Link: https://patch.msgid.link/20251029-work-namespace-nstree-listns-v4-52-2e6f823ebdc0@kernel.org
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>

+119
+119
tools/testing/selftests/namespaces/listns_permissions_test.c
··· 442 442 TH_LOG("LISTNS_CURRENT_USER returned %zd namespaces", count); 443 443 } 444 444 445 + /* 446 + * Test that CAP_SYS_ADMIN in parent user namespace allows seeing 447 + * child user namespace's owned namespaces. 448 + */ 449 + TEST(listns_parent_userns_cap_sys_admin) 450 + { 451 + int pipefd[2]; 452 + pid_t pid; 453 + int status; 454 + bool found_child_userns; 455 + ssize_t count; 456 + 457 + ASSERT_EQ(pipe(pipefd), 0); 458 + 459 + pid = fork(); 460 + ASSERT_GE(pid, 0); 461 + 462 + if (pid == 0) { 463 + int fd; 464 + __u64 parent_userns_id; 465 + __u64 child_userns_id; 466 + struct ns_id_req req; 467 + __u64 ns_ids[100]; 468 + ssize_t ret; 469 + bool found_child_userns; 470 + 471 + close(pipefd[0]); 472 + 473 + /* Create parent user namespace - we have CAP_SYS_ADMIN in it */ 474 + if (setup_userns() < 0) { 475 + close(pipefd[1]); 476 + exit(1); 477 + } 478 + 479 + /* Get parent user namespace ID */ 480 + fd = open("/proc/self/ns/user", O_RDONLY); 481 + if (fd < 0) { 482 + close(pipefd[1]); 483 + exit(1); 484 + } 485 + 486 + if (ioctl(fd, NS_GET_ID, &parent_userns_id) < 0) { 487 + close(fd); 488 + close(pipefd[1]); 489 + exit(1); 490 + } 491 + close(fd); 492 + 493 + /* Create child user namespace */ 494 + if (setup_userns() < 0) { 495 + close(pipefd[1]); 496 + exit(1); 497 + } 498 + 499 + /* Get child user namespace ID */ 500 + fd = open("/proc/self/ns/user", O_RDONLY); 501 + if (fd < 0) { 502 + close(pipefd[1]); 503 + exit(1); 504 + } 505 + 506 + if (ioctl(fd, NS_GET_ID, &child_userns_id) < 0) { 507 + close(fd); 508 + close(pipefd[1]); 509 + exit(1); 510 + } 511 + close(fd); 512 + 513 + /* Create namespaces owned by child user namespace */ 514 + if (unshare(CLONE_NEWNET) < 0) { 515 + close(pipefd[1]); 516 + exit(1); 517 + } 518 + 519 + /* List namespaces owned by parent user namespace */ 520 + req.size = sizeof(req); 521 + req.spare = 0; 522 + req.ns_id = 0; 523 + req.ns_type = 0; 524 + req.spare2 = 0; 525 + req.user_ns_id = parent_userns_id; 526 + 527 + ret = sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); 528 + 529 + /* Should see child user namespace in the list */ 530 + found_child_userns = false; 531 + if (ret > 0) { 532 + for (ssize_t i = 0; i < ret; i++) { 533 + if (ns_ids[i] == child_userns_id) { 534 + found_child_userns = true; 535 + break; 536 + } 537 + } 538 + } 539 + 540 + write(pipefd[1], &found_child_userns, sizeof(found_child_userns)); 541 + write(pipefd[1], &ret, sizeof(ret)); 542 + close(pipefd[1]); 543 + exit(0); 544 + } 545 + 546 + /* Parent */ 547 + close(pipefd[1]); 548 + 549 + found_child_userns = false; 550 + count = 0; 551 + read(pipefd[0], &found_child_userns, sizeof(found_child_userns)); 552 + read(pipefd[0], &count, sizeof(count)); 553 + close(pipefd[0]); 554 + 555 + waitpid(pid, &status, 0); 556 + ASSERT_TRUE(WIFEXITED(status)); 557 + ASSERT_EQ(WEXITSTATUS(status), 0); 558 + 559 + ASSERT_TRUE(found_child_userns); 560 + TH_LOG("Process with CAP_SYS_ADMIN in parent user namespace saw child user namespace (total: %zd)", 561 + count); 562 + } 563 + 445 564 TEST_HARNESS_MAIN