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

selftests/namespaces: sixth listns() permission test

Test that we can see user namespaces we have CAP_SYS_ADMIN inside of.
This is different from seeing namespaces owned by a user namespace.

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

+87
+87
tools/testing/selftests/namespaces/listns_permissions_test.c
··· 561 561 count); 562 562 } 563 563 564 + /* 565 + * Test that we can see user namespaces we have CAP_SYS_ADMIN inside of. 566 + * This is different from seeing namespaces owned by a user namespace. 567 + */ 568 + TEST(listns_cap_sys_admin_inside_userns) 569 + { 570 + int pipefd[2]; 571 + pid_t pid; 572 + int status; 573 + bool found_ours; 574 + 575 + ASSERT_EQ(pipe(pipefd), 0); 576 + 577 + pid = fork(); 578 + ASSERT_GE(pid, 0); 579 + 580 + if (pid == 0) { 581 + int fd; 582 + __u64 our_userns_id; 583 + struct ns_id_req req; 584 + __u64 ns_ids[100]; 585 + ssize_t ret; 586 + bool found_ours; 587 + 588 + close(pipefd[0]); 589 + 590 + /* Create user namespace - we have CAP_SYS_ADMIN inside it */ 591 + if (setup_userns() < 0) { 592 + close(pipefd[1]); 593 + exit(1); 594 + } 595 + 596 + /* Get our user namespace ID */ 597 + fd = open("/proc/self/ns/user", O_RDONLY); 598 + if (fd < 0) { 599 + close(pipefd[1]); 600 + exit(1); 601 + } 602 + 603 + if (ioctl(fd, NS_GET_ID, &our_userns_id) < 0) { 604 + close(fd); 605 + close(pipefd[1]); 606 + exit(1); 607 + } 608 + close(fd); 609 + 610 + /* List all user namespaces globally */ 611 + req.size = sizeof(req); 612 + req.spare = 0; 613 + req.ns_id = 0; 614 + req.ns_type = CLONE_NEWUSER; 615 + req.spare2 = 0; 616 + req.user_ns_id = 0; 617 + 618 + ret = sys_listns(&req, ns_ids, ARRAY_SIZE(ns_ids), 0); 619 + 620 + /* We should be able to see our own user namespace */ 621 + found_ours = false; 622 + if (ret > 0) { 623 + for (ssize_t i = 0; i < ret; i++) { 624 + if (ns_ids[i] == our_userns_id) { 625 + found_ours = true; 626 + break; 627 + } 628 + } 629 + } 630 + 631 + write(pipefd[1], &found_ours, sizeof(found_ours)); 632 + close(pipefd[1]); 633 + exit(0); 634 + } 635 + 636 + /* Parent */ 637 + close(pipefd[1]); 638 + 639 + found_ours = false; 640 + read(pipefd[0], &found_ours, sizeof(found_ours)); 641 + close(pipefd[0]); 642 + 643 + waitpid(pid, &status, 0); 644 + ASSERT_TRUE(WIFEXITED(status)); 645 + ASSERT_EQ(WEXITSTATUS(status), 0); 646 + 647 + ASSERT_TRUE(found_ours); 648 + TH_LOG("Process can see user namespace it has CAP_SYS_ADMIN inside of"); 649 + } 650 + 564 651 TEST_HARNESS_MAIN