xref: /linux/tools/testing/selftests/namespaces/ns_active_ref_test.c (revision 6bdce845fd5add4a69bc7a8101bf1741822d5de0)
1 // SPDX-License-Identifier: GPL-2.0
2 #define _GNU_SOURCE
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <limits.h>
6 #include <sched.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <linux/nsfs.h>
11 #include <sys/mount.h>
12 #include <sys/stat.h>
13 #include <sys/types.h>
14 #include <sys/wait.h>
15 #include <unistd.h>
16 #include "../kselftest_harness.h"
17 #include "../filesystems/utils.h"
18 
19 #ifndef FD_NSFS_ROOT
20 #define FD_NSFS_ROOT -10003 /* Root of the nsfs filesystem */
21 #endif
22 
23 /*
24  * Test that initial namespaces can be reopened via file handle.
25  * Initial namespaces should have active ref count of 1 from boot.
26  */
27 TEST(init_ns_always_active)
28 {
29 	struct file_handle *handle;
30 	int mount_id;
31 	int ret;
32 	int fd1, fd2;
33 	struct stat st1, st2;
34 
35 	handle = malloc(sizeof(*handle) + MAX_HANDLE_SZ);
36 	ASSERT_NE(handle, NULL);
37 
38 	/* Open initial network namespace */
39 	fd1 = open("/proc/1/ns/net", O_RDONLY);
40 	ASSERT_GE(fd1, 0);
41 
42 	/* Get file handle for initial namespace */
43 	handle->handle_bytes = MAX_HANDLE_SZ;
44 	ret = name_to_handle_at(fd1, "", handle, &mount_id, AT_EMPTY_PATH);
45 	if (ret < 0 && errno == EOPNOTSUPP) {
46 		SKIP(free(handle); close(fd1);
47 		     return, "nsfs doesn't support file handles");
48 	}
49 	ASSERT_EQ(ret, 0);
50 
51 	/* Close the namespace fd */
52 	close(fd1);
53 
54 	/* Try to reopen via file handle - should succeed since init ns is always active */
55 	fd2 = open_by_handle_at(FD_NSFS_ROOT, handle, O_RDONLY);
56 	if (fd2 < 0 && (errno == EINVAL || errno == EOPNOTSUPP)) {
57 		SKIP(free(handle);
58 		     return, "open_by_handle_at with FD_NSFS_ROOT not supported");
59 	}
60 	ASSERT_GE(fd2, 0);
61 
62 	/* Verify we opened the same namespace */
63 	fd1 = open("/proc/1/ns/net", O_RDONLY);
64 	ASSERT_GE(fd1, 0);
65 	ASSERT_EQ(fstat(fd1, &st1), 0);
66 	ASSERT_EQ(fstat(fd2, &st2), 0);
67 	ASSERT_EQ(st1.st_ino, st2.st_ino);
68 
69 	close(fd1);
70 	close(fd2);
71 	free(handle);
72 }
73 
74 TEST_HARNESS_MAIN
75