1 // SPDX-License-Identifier: GPL-2.0
6 #include <linux/kernel.h>
15 #include "../kselftest_harness.h"
16 #include "../clone3/clone3_selftests.h"
18 #ifndef __NR_close_range
19 #define __NR_close_range -1
22 #ifndef CLOSE_RANGE_UNSHARE
23 #define CLOSE_RANGE_UNSHARE (1U << 1)
26 static inline int sys_close_range(unsigned int fd, unsigned int max_fd,
29 return syscall(__NR_close_range, fd, max_fd, flags);
33 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
41 for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
44 fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
47 XFAIL(return, "Skipping test since /dev/null does not exist");
53 EXPECT_EQ(-1, sys_close_range(open_fds[0], open_fds[100], -1)) {
55 XFAIL(return, "close_range() syscall not supported");
58 EXPECT_EQ(0, sys_close_range(open_fds[0], open_fds[50], 0));
60 for (i = 0; i <= 50; i++)
61 EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
63 for (i = 51; i <= 100; i++)
64 EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
66 /* create a couple of gaps */
74 EXPECT_EQ(0, sys_close_range(open_fds[51], open_fds[92], 0));
76 for (i = 51; i <= 92; i++)
77 EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
79 for (i = 93; i <= 100; i++)
80 EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
82 /* test that the kernel caps and still closes all fds */
83 EXPECT_EQ(0, sys_close_range(open_fds[93], open_fds[99], 0));
85 for (i = 93; i <= 99; i++)
86 EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
88 EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
90 EXPECT_EQ(0, sys_close_range(open_fds[100], open_fds[100], 0));
92 EXPECT_EQ(-1, fcntl(open_fds[100], F_GETFL));
95 TEST(close_range_unshare)
100 struct clone_args args = {
101 .flags = CLONE_FILES,
102 .exit_signal = SIGCHLD,
105 for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
108 fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
111 XFAIL(return, "Skipping test since /dev/null does not exist");
117 pid = sys_clone3(&args, sizeof(args));
121 ret = sys_close_range(open_fds[0], open_fds[50],
122 CLOSE_RANGE_UNSHARE);
126 for (i = 0; i <= 50; i++)
127 if (fcntl(open_fds[i], F_GETFL) != -1)
130 for (i = 51; i <= 100; i++)
131 if (fcntl(open_fds[i], F_GETFL) == -1)
134 /* create a couple of gaps */
142 ret = sys_close_range(open_fds[51], open_fds[92],
143 CLOSE_RANGE_UNSHARE);
147 for (i = 51; i <= 92; i++)
148 if (fcntl(open_fds[i], F_GETFL) != -1)
151 for (i = 93; i <= 100; i++)
152 if (fcntl(open_fds[i], F_GETFL) == -1)
155 /* test that the kernel caps and still closes all fds */
156 ret = sys_close_range(open_fds[93], open_fds[99],
157 CLOSE_RANGE_UNSHARE);
161 for (i = 93; i <= 99; i++)
162 if (fcntl(open_fds[i], F_GETFL) != -1)
165 if (fcntl(open_fds[100], F_GETFL) == -1)
168 ret = sys_close_range(open_fds[100], open_fds[100],
169 CLOSE_RANGE_UNSHARE);
173 if (fcntl(open_fds[100], F_GETFL) != -1)
179 EXPECT_EQ(waitpid(pid, &status, 0), pid);
180 EXPECT_EQ(true, WIFEXITED(status));
181 EXPECT_EQ(0, WEXITSTATUS(status));
184 TEST(close_range_unshare_capped)
189 struct clone_args args = {
190 .flags = CLONE_FILES,
191 .exit_signal = SIGCHLD,
194 for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
197 fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
200 XFAIL(return, "Skipping test since /dev/null does not exist");
206 pid = sys_clone3(&args, sizeof(args));
210 ret = sys_close_range(open_fds[0], UINT_MAX,
211 CLOSE_RANGE_UNSHARE);
215 for (i = 0; i <= 100; i++)
216 if (fcntl(open_fds[i], F_GETFL) != -1)
222 EXPECT_EQ(waitpid(pid, &status, 0), pid);
223 EXPECT_EQ(true, WIFEXITED(status));
224 EXPECT_EQ(0, WEXITSTATUS(status));