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

selftests/namespaces: fifteenth active reference count tests

Test different namespace types (net, uts, ipc) all contributing
active references to the same owning user namespace.

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

+164
+164
tools/testing/selftests/namespaces/ns_active_ref_test.c
··· 1949 1949 ASSERT_LT(ua_fd, 0); 1950 1950 } 1951 1951 1952 + /* 1953 + * Test different namespace types (net, uts, ipc) all contributing 1954 + * active references to the same owning user namespace. 1955 + */ 1956 + TEST(ns_mixed_types_same_owner) 1957 + { 1958 + struct file_handle *user_handle, *net_handle, *uts_handle; 1959 + int ret, pipefd[2]; 1960 + pid_t pid; 1961 + int status; 1962 + __u64 u_id, n_id, ut_id; 1963 + char u_buf[sizeof(*user_handle) + MAX_HANDLE_SZ]; 1964 + char n_buf[sizeof(*net_handle) + MAX_HANDLE_SZ]; 1965 + char ut_buf[sizeof(*uts_handle) + MAX_HANDLE_SZ]; 1966 + 1967 + ASSERT_EQ(pipe(pipefd), 0); 1968 + pid = fork(); 1969 + ASSERT_GE(pid, 0); 1970 + 1971 + if (pid == 0) { 1972 + close(pipefd[0]); 1973 + 1974 + if (setup_userns() < 0) { 1975 + close(pipefd[1]); 1976 + exit(1); 1977 + } 1978 + 1979 + int u_fd = open("/proc/self/ns/user", O_RDONLY); 1980 + if (u_fd < 0) { 1981 + close(pipefd[1]); 1982 + exit(1); 1983 + } 1984 + if (ioctl(u_fd, NS_GET_ID, &u_id) < 0) { 1985 + close(u_fd); 1986 + close(pipefd[1]); 1987 + exit(1); 1988 + } 1989 + close(u_fd); 1990 + 1991 + if (unshare(CLONE_NEWNET) < 0) { 1992 + close(pipefd[1]); 1993 + exit(1); 1994 + } 1995 + 1996 + int n_fd = open("/proc/self/ns/net", O_RDONLY); 1997 + if (n_fd < 0) { 1998 + close(pipefd[1]); 1999 + exit(1); 2000 + } 2001 + if (ioctl(n_fd, NS_GET_ID, &n_id) < 0) { 2002 + close(n_fd); 2003 + close(pipefd[1]); 2004 + exit(1); 2005 + } 2006 + close(n_fd); 2007 + 2008 + if (unshare(CLONE_NEWUTS) < 0) { 2009 + close(pipefd[1]); 2010 + exit(1); 2011 + } 2012 + 2013 + int ut_fd = open("/proc/self/ns/uts", O_RDONLY); 2014 + if (ut_fd < 0) { 2015 + close(pipefd[1]); 2016 + exit(1); 2017 + } 2018 + if (ioctl(ut_fd, NS_GET_ID, &ut_id) < 0) { 2019 + close(ut_fd); 2020 + close(pipefd[1]); 2021 + exit(1); 2022 + } 2023 + close(ut_fd); 2024 + 2025 + /* Send all namespace IDs */ 2026 + write(pipefd[1], &u_id, sizeof(u_id)); 2027 + write(pipefd[1], &n_id, sizeof(n_id)); 2028 + write(pipefd[1], &ut_id, sizeof(ut_id)); 2029 + close(pipefd[1]); 2030 + exit(0); 2031 + } 2032 + 2033 + close(pipefd[1]); 2034 + 2035 + /* Read all three namespace IDs - fixed size, no parsing needed */ 2036 + ret = read(pipefd[0], &u_id, sizeof(u_id)); 2037 + if (ret != sizeof(u_id)) { 2038 + close(pipefd[0]); 2039 + waitpid(pid, NULL, 0); 2040 + SKIP(return, "Failed to read user namespace ID"); 2041 + } 2042 + 2043 + ret = read(pipefd[0], &n_id, sizeof(n_id)); 2044 + if (ret != sizeof(n_id)) { 2045 + close(pipefd[0]); 2046 + waitpid(pid, NULL, 0); 2047 + SKIP(return, "Failed to read network namespace ID"); 2048 + } 2049 + 2050 + ret = read(pipefd[0], &ut_id, sizeof(ut_id)); 2051 + close(pipefd[0]); 2052 + if (ret != sizeof(ut_id)) { 2053 + waitpid(pid, NULL, 0); 2054 + SKIP(return, "Failed to read UTS namespace ID"); 2055 + } 2056 + 2057 + /* Construct file handles from namespace IDs */ 2058 + user_handle = (struct file_handle *)u_buf; 2059 + user_handle->handle_bytes = sizeof(struct nsfs_file_handle); 2060 + user_handle->handle_type = FILEID_NSFS; 2061 + struct nsfs_file_handle *u_fh = (struct nsfs_file_handle *)user_handle->f_handle; 2062 + u_fh->ns_id = u_id; 2063 + u_fh->ns_type = 0; 2064 + u_fh->ns_inum = 0; 2065 + 2066 + net_handle = (struct file_handle *)n_buf; 2067 + net_handle->handle_bytes = sizeof(struct nsfs_file_handle); 2068 + net_handle->handle_type = FILEID_NSFS; 2069 + struct nsfs_file_handle *n_fh = (struct nsfs_file_handle *)net_handle->f_handle; 2070 + n_fh->ns_id = n_id; 2071 + n_fh->ns_type = 0; 2072 + n_fh->ns_inum = 0; 2073 + 2074 + uts_handle = (struct file_handle *)ut_buf; 2075 + uts_handle->handle_bytes = sizeof(struct nsfs_file_handle); 2076 + uts_handle->handle_type = FILEID_NSFS; 2077 + struct nsfs_file_handle *ut_fh = (struct nsfs_file_handle *)uts_handle->f_handle; 2078 + ut_fh->ns_id = ut_id; 2079 + ut_fh->ns_type = 0; 2080 + ut_fh->ns_inum = 0; 2081 + 2082 + /* Open both non-user namespaces */ 2083 + int n_fd = open_by_handle_at(FD_NSFS_ROOT, net_handle, O_RDONLY); 2084 + int ut_fd = open_by_handle_at(FD_NSFS_ROOT, uts_handle, O_RDONLY); 2085 + if (n_fd < 0 || ut_fd < 0) { 2086 + if (n_fd >= 0) close(n_fd); 2087 + if (ut_fd >= 0) close(ut_fd); 2088 + waitpid(pid, NULL, 0); 2089 + SKIP(return, "Failed to open namespaces"); 2090 + } 2091 + 2092 + waitpid(pid, &status, 0); 2093 + ASSERT_TRUE(WIFEXITED(status)); 2094 + ASSERT_EQ(WEXITSTATUS(status), 0); 2095 + 2096 + /* User namespace should be active (2 active children) */ 2097 + TH_LOG("Both net and uts active - user ns should be active"); 2098 + int u_fd = open_by_handle_at(FD_NSFS_ROOT, user_handle, O_RDONLY); 2099 + ASSERT_GE(u_fd, 0); 2100 + close(u_fd); 2101 + 2102 + /* Close net - user ns should STILL be active (uts still active) */ 2103 + TH_LOG("Closing net - user ns should still be active"); 2104 + close(n_fd); 2105 + u_fd = open_by_handle_at(FD_NSFS_ROOT, user_handle, O_RDONLY); 2106 + ASSERT_GE(u_fd, 0); 2107 + close(u_fd); 2108 + 2109 + /* Close uts - user ns should become inactive */ 2110 + TH_LOG("Closing uts - user ns should become inactive"); 2111 + close(ut_fd); 2112 + u_fd = open_by_handle_at(FD_NSFS_ROOT, user_handle, O_RDONLY); 2113 + ASSERT_LT(u_fd, 0); 2114 + } 2115 + 1952 2116 TEST_HARNESS_MAIN