Skip to content

Commit 615ab43

Browse files
Christian Braunerbrauner
authored andcommitted
tests/pid_namespace: add pid_max tests
Signed-off-by: Alexander Mikhalitsyn <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Christian Brauner <[email protected]>
1 parent 7863dcc commit 615ab43

File tree

3 files changed

+360
-1
lines changed

3 files changed

+360
-1
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
pid_max
12
regression_enomem

tools/testing/selftests/pid_namespace/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# SPDX-License-Identifier: GPL-2.0
22
CFLAGS += -g $(KHDR_INCLUDES)
33

4-
TEST_GEN_PROGS = regression_enomem
4+
TEST_GEN_PROGS = regression_enomem pid_max
55

66
LOCAL_HDRS += $(selfdir)/pidfd/pidfd.h
77

Lines changed: 358 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,358 @@
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

0 commit comments

Comments
 (0)