1*9f34c566SMichal Koutný // SPDX-License-Identifier: GPL-2.0
2*9f34c566SMichal Koutný #define _GNU_SOURCE
3*9f34c566SMichal Koutný
4*9f34c566SMichal Koutný #include <errno.h>
5*9f34c566SMichal Koutný #include <linux/limits.h>
6*9f34c566SMichal Koutný #include <signal.h>
7*9f34c566SMichal Koutný #include <string.h>
8*9f34c566SMichal Koutný #include <sys/stat.h>
9*9f34c566SMichal Koutný #include <sys/types.h>
10*9f34c566SMichal Koutný #include <unistd.h>
11*9f34c566SMichal Koutný
12*9f34c566SMichal Koutný #include "../kselftest.h"
13*9f34c566SMichal Koutný #include "cgroup_util.h"
14*9f34c566SMichal Koutný
run_success(const char * cgroup,void * arg)15*9f34c566SMichal Koutný static int run_success(const char *cgroup, void *arg)
16*9f34c566SMichal Koutný {
17*9f34c566SMichal Koutný return 0;
18*9f34c566SMichal Koutný }
19*9f34c566SMichal Koutný
run_pause(const char * cgroup,void * arg)20*9f34c566SMichal Koutný static int run_pause(const char *cgroup, void *arg)
21*9f34c566SMichal Koutný {
22*9f34c566SMichal Koutný return pause();
23*9f34c566SMichal Koutný }
24*9f34c566SMichal Koutný
25*9f34c566SMichal Koutný /*
26*9f34c566SMichal Koutný * This test checks that pids.max prevents forking new children above the
27*9f34c566SMichal Koutný * specified limit in the cgroup.
28*9f34c566SMichal Koutný */
test_pids_max(const char * root)29*9f34c566SMichal Koutný static int test_pids_max(const char *root)
30*9f34c566SMichal Koutný {
31*9f34c566SMichal Koutný int ret = KSFT_FAIL;
32*9f34c566SMichal Koutný char *cg_pids;
33*9f34c566SMichal Koutný int pid;
34*9f34c566SMichal Koutný
35*9f34c566SMichal Koutný cg_pids = cg_name(root, "pids_test");
36*9f34c566SMichal Koutný if (!cg_pids)
37*9f34c566SMichal Koutný goto cleanup;
38*9f34c566SMichal Koutný
39*9f34c566SMichal Koutný if (cg_create(cg_pids))
40*9f34c566SMichal Koutný goto cleanup;
41*9f34c566SMichal Koutný
42*9f34c566SMichal Koutný if (cg_read_strcmp(cg_pids, "pids.max", "max\n"))
43*9f34c566SMichal Koutný goto cleanup;
44*9f34c566SMichal Koutný
45*9f34c566SMichal Koutný if (cg_write(cg_pids, "pids.max", "2"))
46*9f34c566SMichal Koutný goto cleanup;
47*9f34c566SMichal Koutný
48*9f34c566SMichal Koutný if (cg_enter_current(cg_pids))
49*9f34c566SMichal Koutný goto cleanup;
50*9f34c566SMichal Koutný
51*9f34c566SMichal Koutný pid = cg_run_nowait(cg_pids, run_pause, NULL);
52*9f34c566SMichal Koutný if (pid < 0)
53*9f34c566SMichal Koutný goto cleanup;
54*9f34c566SMichal Koutný
55*9f34c566SMichal Koutný if (cg_run_nowait(cg_pids, run_success, NULL) != -1 || errno != EAGAIN)
56*9f34c566SMichal Koutný goto cleanup;
57*9f34c566SMichal Koutný
58*9f34c566SMichal Koutný if (kill(pid, SIGINT))
59*9f34c566SMichal Koutný goto cleanup;
60*9f34c566SMichal Koutný
61*9f34c566SMichal Koutný ret = KSFT_PASS;
62*9f34c566SMichal Koutný
63*9f34c566SMichal Koutný cleanup:
64*9f34c566SMichal Koutný cg_enter_current(root);
65*9f34c566SMichal Koutný cg_destroy(cg_pids);
66*9f34c566SMichal Koutný free(cg_pids);
67*9f34c566SMichal Koutný
68*9f34c566SMichal Koutný return ret;
69*9f34c566SMichal Koutný }
70*9f34c566SMichal Koutný
71*9f34c566SMichal Koutný /*
72*9f34c566SMichal Koutný * This test checks that pids.events are counted in cgroup associated with pids.max
73*9f34c566SMichal Koutný */
test_pids_events(const char * root)74*9f34c566SMichal Koutný static int test_pids_events(const char *root)
75*9f34c566SMichal Koutný {
76*9f34c566SMichal Koutný int ret = KSFT_FAIL;
77*9f34c566SMichal Koutný char *cg_parent = NULL, *cg_child = NULL;
78*9f34c566SMichal Koutný int pid;
79*9f34c566SMichal Koutný
80*9f34c566SMichal Koutný cg_parent = cg_name(root, "pids_parent");
81*9f34c566SMichal Koutný cg_child = cg_name(cg_parent, "pids_child");
82*9f34c566SMichal Koutný if (!cg_parent || !cg_child)
83*9f34c566SMichal Koutný goto cleanup;
84*9f34c566SMichal Koutný
85*9f34c566SMichal Koutný if (cg_create(cg_parent))
86*9f34c566SMichal Koutný goto cleanup;
87*9f34c566SMichal Koutný if (cg_write(cg_parent, "cgroup.subtree_control", "+pids"))
88*9f34c566SMichal Koutný goto cleanup;
89*9f34c566SMichal Koutný if (cg_create(cg_child))
90*9f34c566SMichal Koutný goto cleanup;
91*9f34c566SMichal Koutný
92*9f34c566SMichal Koutný if (cg_write(cg_parent, "pids.max", "2"))
93*9f34c566SMichal Koutný goto cleanup;
94*9f34c566SMichal Koutný
95*9f34c566SMichal Koutný if (cg_read_strcmp(cg_child, "pids.max", "max\n"))
96*9f34c566SMichal Koutný goto cleanup;
97*9f34c566SMichal Koutný
98*9f34c566SMichal Koutný if (cg_enter_current(cg_child))
99*9f34c566SMichal Koutný goto cleanup;
100*9f34c566SMichal Koutný
101*9f34c566SMichal Koutný pid = cg_run_nowait(cg_child, run_pause, NULL);
102*9f34c566SMichal Koutný if (pid < 0)
103*9f34c566SMichal Koutný goto cleanup;
104*9f34c566SMichal Koutný
105*9f34c566SMichal Koutný if (cg_run_nowait(cg_child, run_success, NULL) != -1 || errno != EAGAIN)
106*9f34c566SMichal Koutný goto cleanup;
107*9f34c566SMichal Koutný
108*9f34c566SMichal Koutný if (kill(pid, SIGINT))
109*9f34c566SMichal Koutný goto cleanup;
110*9f34c566SMichal Koutný
111*9f34c566SMichal Koutný if (cg_read_key_long(cg_child, "pids.events", "max ") != 0)
112*9f34c566SMichal Koutný goto cleanup;
113*9f34c566SMichal Koutný if (cg_read_key_long(cg_parent, "pids.events", "max ") != 1)
114*9f34c566SMichal Koutný goto cleanup;
115*9f34c566SMichal Koutný
116*9f34c566SMichal Koutný
117*9f34c566SMichal Koutný ret = KSFT_PASS;
118*9f34c566SMichal Koutný
119*9f34c566SMichal Koutný cleanup:
120*9f34c566SMichal Koutný cg_enter_current(root);
121*9f34c566SMichal Koutný if (cg_child)
122*9f34c566SMichal Koutný cg_destroy(cg_child);
123*9f34c566SMichal Koutný if (cg_parent)
124*9f34c566SMichal Koutný cg_destroy(cg_parent);
125*9f34c566SMichal Koutný free(cg_child);
126*9f34c566SMichal Koutný free(cg_parent);
127*9f34c566SMichal Koutný
128*9f34c566SMichal Koutný return ret;
129*9f34c566SMichal Koutný }
130*9f34c566SMichal Koutný
131*9f34c566SMichal Koutný
132*9f34c566SMichal Koutný
133*9f34c566SMichal Koutný #define T(x) { x, #x }
134*9f34c566SMichal Koutný struct pids_test {
135*9f34c566SMichal Koutný int (*fn)(const char *root);
136*9f34c566SMichal Koutný const char *name;
137*9f34c566SMichal Koutný } tests[] = {
138*9f34c566SMichal Koutný T(test_pids_max),
139*9f34c566SMichal Koutný T(test_pids_events),
140*9f34c566SMichal Koutný };
141*9f34c566SMichal Koutný #undef T
142*9f34c566SMichal Koutný
main(int argc,char ** argv)143*9f34c566SMichal Koutný int main(int argc, char **argv)
144*9f34c566SMichal Koutný {
145*9f34c566SMichal Koutný char root[PATH_MAX];
146*9f34c566SMichal Koutný
147*9f34c566SMichal Koutný ksft_print_header();
148*9f34c566SMichal Koutný ksft_set_plan(ARRAY_SIZE(tests));
149*9f34c566SMichal Koutný if (cg_find_unified_root(root, sizeof(root), NULL))
150*9f34c566SMichal Koutný ksft_exit_skip("cgroup v2 isn't mounted\n");
151*9f34c566SMichal Koutný
152*9f34c566SMichal Koutný /*
153*9f34c566SMichal Koutný * Check that pids controller is available:
154*9f34c566SMichal Koutný * pids is listed in cgroup.controllers
155*9f34c566SMichal Koutný */
156*9f34c566SMichal Koutný if (cg_read_strstr(root, "cgroup.controllers", "pids"))
157*9f34c566SMichal Koutný ksft_exit_skip("pids controller isn't available\n");
158*9f34c566SMichal Koutný
159*9f34c566SMichal Koutný if (cg_read_strstr(root, "cgroup.subtree_control", "pids"))
160*9f34c566SMichal Koutný if (cg_write(root, "cgroup.subtree_control", "+pids"))
161*9f34c566SMichal Koutný ksft_exit_skip("Failed to set pids controller\n");
162*9f34c566SMichal Koutný
163*9f34c566SMichal Koutný for (int i = 0; i < ARRAY_SIZE(tests); i++) {
164*9f34c566SMichal Koutný switch (tests[i].fn(root)) {
165*9f34c566SMichal Koutný case KSFT_PASS:
166*9f34c566SMichal Koutný ksft_test_result_pass("%s\n", tests[i].name);
167*9f34c566SMichal Koutný break;
168*9f34c566SMichal Koutný case KSFT_SKIP:
169*9f34c566SMichal Koutný ksft_test_result_skip("%s\n", tests[i].name);
170*9f34c566SMichal Koutný break;
171*9f34c566SMichal Koutný default:
172*9f34c566SMichal Koutný ksft_test_result_fail("%s\n", tests[i].name);
173*9f34c566SMichal Koutný break;
174*9f34c566SMichal Koutný }
175*9f34c566SMichal Koutný }
176*9f34c566SMichal Koutný
177*9f34c566SMichal Koutný ksft_finished();
178*9f34c566SMichal Koutný }
179