1 /* SPDX-License-Identifier: GPL-2.0 */
2 #define _GNU_SOURCE
3 #include <assert.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <linux/types.h>
7 #include <sched.h>
8 #include <signal.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <syscall.h>
13 #include <sys/mount.h>
14 #include <sys/wait.h>
15
16 #include "kselftest_harness.h"
17 #include "../pidfd/pidfd.h"
18
19 #define __STACK_SIZE (8 * 1024 * 1024)
do_clone(int (* fn)(void *),void * arg,int flags)20 static pid_t do_clone(int (*fn)(void *), void *arg, int flags)
21 {
22 char *stack;
23 pid_t ret;
24
25 stack = malloc(__STACK_SIZE);
26 if (!stack)
27 return -ENOMEM;
28
29 #ifdef __ia64__
30 ret = __clone2(fn, stack, __STACK_SIZE, flags | SIGCHLD, arg);
31 #else
32 ret = clone(fn, stack + __STACK_SIZE, flags | SIGCHLD, arg);
33 #endif
34 free(stack);
35 return ret;
36 }
37
pid_max_cb(void * data)38 static int pid_max_cb(void *data)
39 {
40 int fd, ret;
41 pid_t pid;
42
43 ret = mount("", "/", NULL, MS_PRIVATE | MS_REC, 0);
44 if (ret) {
45 fprintf(stderr, "%m - Failed to make rootfs private mount\n");
46 return -1;
47 }
48
49 umount2("/proc", MNT_DETACH);
50
51 ret = mount("proc", "/proc", "proc", 0, NULL);
52 if (ret) {
53 fprintf(stderr, "%m - Failed to mount proc\n");
54 return -1;
55 }
56
57 fd = open("/proc/sys/kernel/pid_max", O_RDWR | O_CLOEXEC | O_NOCTTY);
58 if (fd < 0) {
59 fprintf(stderr, "%m - Failed to open pid_max\n");
60 return -1;
61 }
62
63 ret = write(fd, "500", sizeof("500") - 1);
64 if (ret < 0) {
65 fprintf(stderr, "%m - Failed to write pid_max\n");
66 return -1;
67 }
68
69 for (int i = 0; i < 501; i++) {
70 pid = fork();
71 if (pid == 0)
72 exit(EXIT_SUCCESS);
73 wait_for_pid(pid);
74 if (pid > 500) {
75 fprintf(stderr, "Managed to create pid number beyond limit\n");
76 return -1;
77 }
78 }
79
80 return 0;
81 }
82
pid_max_nested_inner(void * data)83 static int pid_max_nested_inner(void *data)
84 {
85 int fret = -1;
86 pid_t pids[2];
87 int fd, i, ret;
88
89 ret = mount("", "/", NULL, MS_PRIVATE | MS_REC, 0);
90 if (ret) {
91 fprintf(stderr, "%m - Failed to make rootfs private mount\n");
92 return fret;
93 }
94
95 umount2("/proc", MNT_DETACH);
96
97 ret = mount("proc", "/proc", "proc", 0, NULL);
98 if (ret) {
99 fprintf(stderr, "%m - Failed to mount proc\n");
100 return fret;
101 }
102
103 fd = open("/proc/sys/kernel/pid_max", O_RDWR | O_CLOEXEC | O_NOCTTY);
104 if (fd < 0) {
105 fprintf(stderr, "%m - Failed to open pid_max\n");
106 return fret;
107 }
108
109 ret = write(fd, "500", sizeof("500") - 1);
110 close(fd);
111 if (ret < 0) {
112 fprintf(stderr, "%m - Failed to write pid_max\n");
113 return fret;
114 }
115
116 pids[0] = fork();
117 if (pids[0] < 0) {
118 fprintf(stderr, "Failed to create first new process\n");
119 return fret;
120 }
121
122 if (pids[0] == 0)
123 exit(EXIT_SUCCESS);
124
125 pids[1] = fork();
126 wait_for_pid(pids[0]);
127 if (pids[1] >= 0) {
128 if (pids[1] == 0)
129 exit(EXIT_SUCCESS);
130 wait_for_pid(pids[1]);
131
132 fprintf(stderr, "Managed to create process even though ancestor pid namespace had a limit\n");
133 return fret;
134 }
135
136 /* Now make sure that we wrap pids at 400. */
137 for (i = 0; i < 510; i++) {
138 pid_t pid;
139
140 pid = fork();
141 if (pid < 0)
142 return fret;
143
144 if (pid == 0)
145 exit(EXIT_SUCCESS);
146
147 wait_for_pid(pid);
148 if (pid >= 500) {
149 fprintf(stderr, "Managed to create process with pid %d beyond configured limit\n", pid);
150 return fret;
151 }
152 }
153
154 return 0;
155 }
156
pid_max_nested_outer(void * data)157 static int pid_max_nested_outer(void *data)
158 {
159 int fret = -1, nr_procs = 400;
160 pid_t pids[1000];
161 int fd, i, ret;
162 pid_t pid;
163
164 ret = mount("", "/", NULL, MS_PRIVATE | MS_REC, 0);
165 if (ret) {
166 fprintf(stderr, "%m - Failed to make rootfs private mount\n");
167 return fret;
168 }
169
170 umount2("/proc", MNT_DETACH);
171
172 ret = mount("proc", "/proc", "proc", 0, NULL);
173 if (ret) {
174 fprintf(stderr, "%m - Failed to mount proc\n");
175 return fret;
176 }
177
178 fd = open("/proc/sys/kernel/pid_max", O_RDWR | O_CLOEXEC | O_NOCTTY);
179 if (fd < 0) {
180 fprintf(stderr, "%m - Failed to open pid_max\n");
181 return fret;
182 }
183
184 ret = write(fd, "400", sizeof("400") - 1);
185 close(fd);
186 if (ret < 0) {
187 fprintf(stderr, "%m - Failed to write pid_max\n");
188 return fret;
189 }
190
191 /*
192 * Create 397 processes. This leaves room for do_clone() (398) and
193 * one more 399. So creating another process needs to fail.
194 */
195 for (nr_procs = 0; nr_procs < 396; nr_procs++) {
196 pid = fork();
197 if (pid < 0)
198 goto reap;
199
200 if (pid == 0)
201 exit(EXIT_SUCCESS);
202
203 pids[nr_procs] = pid;
204 }
205
206 pid = do_clone(pid_max_nested_inner, NULL, CLONE_NEWPID | CLONE_NEWNS);
207 if (pid < 0) {
208 fprintf(stderr, "%m - Failed to clone nested pidns\n");
209 goto reap;
210 }
211
212 if (wait_for_pid(pid)) {
213 fprintf(stderr, "%m - Nested pid_max failed\n");
214 goto reap;
215 }
216
217 fret = 0;
218
219 reap:
220 for (int i = 0; i < nr_procs; i++)
221 wait_for_pid(pids[i]);
222
223 return fret;
224 }
225
pid_max_nested_limit_inner(void * data)226 static int pid_max_nested_limit_inner(void *data)
227 {
228 int fret = -1, nr_procs = 400;
229 int fd, ret;
230 pid_t pid;
231 pid_t pids[1000];
232
233 ret = mount("", "/", NULL, MS_PRIVATE | MS_REC, 0);
234 if (ret) {
235 fprintf(stderr, "%m - Failed to make rootfs private mount\n");
236 return fret;
237 }
238
239 umount2("/proc", MNT_DETACH);
240
241 ret = mount("proc", "/proc", "proc", 0, NULL);
242 if (ret) {
243 fprintf(stderr, "%m - Failed to mount proc\n");
244 return fret;
245 }
246
247 fd = open("/proc/sys/kernel/pid_max", O_RDWR | O_CLOEXEC | O_NOCTTY);
248 if (fd < 0) {
249 fprintf(stderr, "%m - Failed to open pid_max\n");
250 return fret;
251 }
252
253 ret = write(fd, "500", sizeof("500") - 1);
254 close(fd);
255 if (ret < 0) {
256 fprintf(stderr, "%m - Failed to write pid_max\n");
257 return fret;
258 }
259
260 for (nr_procs = 0; nr_procs < 500; nr_procs++) {
261 pid = fork();
262 if (pid < 0)
263 break;
264
265 if (pid == 0)
266 exit(EXIT_SUCCESS);
267
268 pids[nr_procs] = pid;
269 }
270
271 if (nr_procs >= 400) {
272 fprintf(stderr, "Managed to create processes beyond the configured outer limit\n");
273 goto reap;
274 }
275
276 fret = 0;
277
278 reap:
279 for (int i = 0; i < nr_procs; i++)
280 wait_for_pid(pids[i]);
281
282 return fret;
283 }
284
pid_max_nested_limit_outer(void * data)285 static int pid_max_nested_limit_outer(void *data)
286 {
287 int fd, ret;
288 pid_t pid;
289
290 ret = mount("", "/", NULL, MS_PRIVATE | MS_REC, 0);
291 if (ret) {
292 fprintf(stderr, "%m - Failed to make rootfs private mount\n");
293 return -1;
294 }
295
296 umount2("/proc", MNT_DETACH);
297
298 ret = mount("proc", "/proc", "proc", 0, NULL);
299 if (ret) {
300 fprintf(stderr, "%m - Failed to mount proc\n");
301 return -1;
302 }
303
304 fd = open("/proc/sys/kernel/pid_max", O_RDWR | O_CLOEXEC | O_NOCTTY);
305 if (fd < 0) {
306 fprintf(stderr, "%m - Failed to open pid_max\n");
307 return -1;
308 }
309
310 ret = write(fd, "400", sizeof("400") - 1);
311 close(fd);
312 if (ret < 0) {
313 fprintf(stderr, "%m - Failed to write pid_max\n");
314 return -1;
315 }
316
317 pid = do_clone(pid_max_nested_limit_inner, NULL, CLONE_NEWPID | CLONE_NEWNS);
318 if (pid < 0) {
319 fprintf(stderr, "%m - Failed to clone nested pidns\n");
320 return -1;
321 }
322
323 if (wait_for_pid(pid)) {
324 fprintf(stderr, "%m - Nested pid_max failed\n");
325 return -1;
326 }
327
328 return 0;
329 }
330
TEST(pid_max_simple)331 TEST(pid_max_simple)
332 {
333 pid_t pid;
334
335
336 pid = do_clone(pid_max_cb, NULL, CLONE_NEWPID | CLONE_NEWNS);
337 ASSERT_GT(pid, 0);
338 ASSERT_EQ(0, wait_for_pid(pid));
339 }
340
TEST(pid_max_nested_limit)341 TEST(pid_max_nested_limit)
342 {
343 pid_t pid;
344
345 pid = do_clone(pid_max_nested_limit_outer, NULL, CLONE_NEWPID | CLONE_NEWNS);
346 ASSERT_GT(pid, 0);
347 ASSERT_EQ(0, wait_for_pid(pid));
348 }
349
TEST(pid_max_nested)350 TEST(pid_max_nested)
351 {
352 pid_t pid;
353
354 pid = do_clone(pid_max_nested_outer, NULL, CLONE_NEWPID | CLONE_NEWNS);
355 ASSERT_GT(pid, 0);
356 ASSERT_EQ(0, wait_for_pid(pid));
357 }
358
359 TEST_HARNESS_MAIN
360