Merge back cpufreq updates for v5.11.
[linux-2.6-microblaze.git] / tools / testing / selftests / core / close_range_test.c
1 // SPDX-License-Identifier: GPL-2.0
2
3 #define _GNU_SOURCE
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <linux/kernel.h>
7 #include <limits.h>
8 #include <stdbool.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <syscall.h>
13 #include <unistd.h>
14
15 #include "../kselftest_harness.h"
16 #include "../clone3/clone3_selftests.h"
17
18 #ifndef __NR_close_range
19 #define __NR_close_range -1
20 #endif
21
22 #ifndef CLOSE_RANGE_UNSHARE
23 #define CLOSE_RANGE_UNSHARE     (1U << 1)
24 #endif
25
26 static inline int sys_close_range(unsigned int fd, unsigned int max_fd,
27                                   unsigned int flags)
28 {
29         return syscall(__NR_close_range, fd, max_fd, flags);
30 }
31
32 #ifndef ARRAY_SIZE
33 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
34 #endif
35
36 TEST(close_range)
37 {
38         int i, ret;
39         int open_fds[101];
40
41         for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
42                 int fd;
43
44                 fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
45                 ASSERT_GE(fd, 0) {
46                         if (errno == ENOENT)
47                                 XFAIL(return, "Skipping test since /dev/null does not exist");
48                 }
49
50                 open_fds[i] = fd;
51         }
52
53         EXPECT_EQ(-1, sys_close_range(open_fds[0], open_fds[100], -1)) {
54                 if (errno == ENOSYS)
55                         XFAIL(return, "close_range() syscall not supported");
56         }
57
58         EXPECT_EQ(0, sys_close_range(open_fds[0], open_fds[50], 0));
59
60         for (i = 0; i <= 50; i++)
61                 EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
62
63         for (i = 51; i <= 100; i++)
64                 EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
65
66         /* create a couple of gaps */
67         close(57);
68         close(78);
69         close(81);
70         close(82);
71         close(84);
72         close(90);
73
74         EXPECT_EQ(0, sys_close_range(open_fds[51], open_fds[92], 0));
75
76         for (i = 51; i <= 92; i++)
77                 EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
78
79         for (i = 93; i <= 100; i++)
80                 EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
81
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));
84
85         for (i = 93; i <= 99; i++)
86                 EXPECT_EQ(-1, fcntl(open_fds[i], F_GETFL));
87
88         EXPECT_GT(fcntl(open_fds[i], F_GETFL), -1);
89
90         EXPECT_EQ(0, sys_close_range(open_fds[100], open_fds[100], 0));
91
92         EXPECT_EQ(-1, fcntl(open_fds[100], F_GETFL));
93 }
94
95 TEST(close_range_unshare)
96 {
97         int i, ret, status;
98         pid_t pid;
99         int open_fds[101];
100         struct clone_args args = {
101                 .flags = CLONE_FILES,
102                 .exit_signal = SIGCHLD,
103         };
104
105         for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
106                 int fd;
107
108                 fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
109                 ASSERT_GE(fd, 0) {
110                         if (errno == ENOENT)
111                                 XFAIL(return, "Skipping test since /dev/null does not exist");
112                 }
113
114                 open_fds[i] = fd;
115         }
116
117         pid = sys_clone3(&args, sizeof(args));
118         ASSERT_GE(pid, 0);
119
120         if (pid == 0) {
121                 ret = sys_close_range(open_fds[0], open_fds[50],
122                                       CLOSE_RANGE_UNSHARE);
123                 if (ret)
124                         exit(EXIT_FAILURE);
125
126                 for (i = 0; i <= 50; i++)
127                         if (fcntl(open_fds[i], F_GETFL) != -1)
128                                 exit(EXIT_FAILURE);
129
130                 for (i = 51; i <= 100; i++)
131                         if (fcntl(open_fds[i], F_GETFL) == -1)
132                                 exit(EXIT_FAILURE);
133
134                 /* create a couple of gaps */
135                 close(57);
136                 close(78);
137                 close(81);
138                 close(82);
139                 close(84);
140                 close(90);
141
142                 ret = sys_close_range(open_fds[51], open_fds[92],
143                                       CLOSE_RANGE_UNSHARE);
144                 if (ret)
145                         exit(EXIT_FAILURE);
146
147                 for (i = 51; i <= 92; i++)
148                         if (fcntl(open_fds[i], F_GETFL) != -1)
149                                 exit(EXIT_FAILURE);
150
151                 for (i = 93; i <= 100; i++)
152                         if (fcntl(open_fds[i], F_GETFL) == -1)
153                                 exit(EXIT_FAILURE);
154
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);
158                 if (ret)
159                         exit(EXIT_FAILURE);
160
161                 for (i = 93; i <= 99; i++)
162                         if (fcntl(open_fds[i], F_GETFL) != -1)
163                                 exit(EXIT_FAILURE);
164
165                 if (fcntl(open_fds[100], F_GETFL) == -1)
166                         exit(EXIT_FAILURE);
167
168                 ret = sys_close_range(open_fds[100], open_fds[100],
169                                       CLOSE_RANGE_UNSHARE);
170                 if (ret)
171                         exit(EXIT_FAILURE);
172
173                 if (fcntl(open_fds[100], F_GETFL) != -1)
174                         exit(EXIT_FAILURE);
175
176                 exit(EXIT_SUCCESS);
177         }
178
179         EXPECT_EQ(waitpid(pid, &status, 0), pid);
180         EXPECT_EQ(true, WIFEXITED(status));
181         EXPECT_EQ(0, WEXITSTATUS(status));
182 }
183
184 TEST(close_range_unshare_capped)
185 {
186         int i, ret, status;
187         pid_t pid;
188         int open_fds[101];
189         struct clone_args args = {
190                 .flags = CLONE_FILES,
191                 .exit_signal = SIGCHLD,
192         };
193
194         for (i = 0; i < ARRAY_SIZE(open_fds); i++) {
195                 int fd;
196
197                 fd = open("/dev/null", O_RDONLY | O_CLOEXEC);
198                 ASSERT_GE(fd, 0) {
199                         if (errno == ENOENT)
200                                 XFAIL(return, "Skipping test since /dev/null does not exist");
201                 }
202
203                 open_fds[i] = fd;
204         }
205
206         pid = sys_clone3(&args, sizeof(args));
207         ASSERT_GE(pid, 0);
208
209         if (pid == 0) {
210                 ret = sys_close_range(open_fds[0], UINT_MAX,
211                                       CLOSE_RANGE_UNSHARE);
212                 if (ret)
213                         exit(EXIT_FAILURE);
214
215                 for (i = 0; i <= 100; i++)
216                         if (fcntl(open_fds[i], F_GETFL) != -1)
217                                 exit(EXIT_FAILURE);
218
219                 exit(EXIT_SUCCESS);
220         }
221
222         EXPECT_EQ(waitpid(pid, &status, 0), pid);
223         EXPECT_EQ(true, WIFEXITED(status));
224         EXPECT_EQ(0, WEXITSTATUS(status));
225 }
226
227 TEST_HARNESS_MAIN