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