xref: /linux/tools/testing/selftests/pid_namespace/pid_max.c (revision 2d2435e1c843ced85e55885282c866208ff9f676)
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)
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 
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 
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 
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 
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 
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 
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 
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 
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