]> git.ipfire.org Git - pakfire.git/blob - tests/libpakfire/jail.c
cgroup: Add option to control the amount of PIDs
[pakfire.git] / tests / libpakfire / jail.c
1 /*#############################################################################
2 # #
3 # Pakfire - The IPFire package management system #
4 # Copyright (C) 2022 Pakfire development team #
5 # #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
10 # #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
15 # #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
18 # #
19 #############################################################################*/
20
21 #include <pakfire/cgroup.h>
22 #include <pakfire/jail.h>
23
24 #include "../testsuite.h"
25
26 static const char* cmd_hello_world[] = {
27 "/command", "echo", "Hello World!", NULL,
28 };
29
30 static int test_create(const struct test* t) {
31 struct pakfire_jail* jail = NULL;
32
33 // Create a new jail
34 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
35
36 // Destroy it
37 ASSERT_NULL(pakfire_jail_unref(jail));
38
39 // Create an interactive jail
40 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, PAKFIRE_JAIL_INTERACTIVE));
41
42 // Destroy it again
43 ASSERT_NULL(pakfire_jail_unref(jail));
44
45 return EXIT_SUCCESS;
46
47 FAIL:
48 return EXIT_FAILURE;
49 }
50
51 static int test_env(const struct test* t) {
52 struct pakfire_jail* jail = NULL;
53
54 // Create a new jail
55 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
56
57 // Check if the default variables are set
58 ASSERT(pakfire_jail_get_env(jail, "LANG"));
59 ASSERT(pakfire_jail_get_env(jail, "TERM"));
60
61 // Fetch a non-existing environment variable
62 ASSERT_NULL(pakfire_jail_get_env(jail, "VARIABLE"));
63
64 // Set a variable
65 ASSERT_SUCCESS(pakfire_jail_set_env(jail, "VARIABLE", "VALUE"));
66
67 // Read the value back
68 ASSERT_STRING_EQUALS(pakfire_jail_get_env(jail, "VARIABLE"), "VALUE");
69
70 // Destroy it
71 ASSERT_NULL(pakfire_jail_unref(jail));
72
73 return EXIT_SUCCESS;
74
75 FAIL:
76 return EXIT_FAILURE;
77 }
78
79 static int test_exec(const struct test* t) {
80 struct pakfire_jail* jail = NULL;
81
82 // Create a new jail
83 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
84
85 // Try to execute something
86 ASSERT_SUCCESS(pakfire_jail_exec(jail, cmd_hello_world, NULL));
87
88 // Destroy it
89 ASSERT_NULL(pakfire_jail_unref(jail));
90
91 return EXIT_SUCCESS;
92
93 FAIL:
94 return EXIT_FAILURE;
95 }
96
97 static int test_launch_into_cgroup(const struct test* t) {
98 struct pakfire_cgroup* cgroup = NULL;
99 struct pakfire_jail* jail = NULL;
100 int r = EXIT_FAILURE;
101
102 // Create a new cgroup
103 ASSERT_SUCCESS(pakfire_cgroup_open(&cgroup, t->pakfire, "pakfire-test", 0));
104
105 // Create a new jail
106 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
107
108 // Connect jail to the cgroup
109 ASSERT_SUCCESS(pakfire_jail_set_cgroup(jail, cgroup));
110
111 // Run command
112 ASSERT(pakfire_jail_exec(jail, cmd_hello_world, NULL) == 0);
113
114 r = EXIT_SUCCESS;
115
116 FAIL:
117 if (cgroup) {
118 pakfire_cgroup_destroy(cgroup);
119 pakfire_cgroup_unref(cgroup);
120 }
121 if (jail)
122 pakfire_jail_unref(jail);
123
124 return r;
125 }
126
127 static int test_nice(const struct test* t) {
128 struct pakfire_jail* jail = NULL;
129 char* output = NULL;
130 int r = EXIT_FAILURE;
131
132 const char* argv[] = {
133 "/command", "print-nice", NULL,
134 };
135
136 // Create a new jail
137 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
138
139 // Set invalid nice levels
140 ASSERT_ERRNO(pakfire_jail_nice(jail, 100), EINVAL);
141 ASSERT_ERRNO(pakfire_jail_nice(jail, -100), EINVAL);
142
143 // Set something sane
144 ASSERT_SUCCESS(pakfire_jail_nice(jail, 5));
145
146 // Check if the nice level has been set
147 ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, &output));
148 ASSERT_STRING_EQUALS(output, "5\n");
149
150 // Success
151 r = EXIT_SUCCESS;
152
153 FAIL:
154 if (jail)
155 pakfire_jail_unref(jail);
156 if (output)
157 free(output);
158
159 return r;
160 }
161
162 static int test_memory_limit(const struct test* t) {
163 struct pakfire_cgroup* cgroup = NULL;
164 struct pakfire_jail* jail = NULL;
165 int r = EXIT_FAILURE;
166
167 const char* argv[] = {
168 "/command", "exhaust-memory", NULL,
169 };
170
171 // Create cgroup
172 ASSERT_SUCCESS(pakfire_cgroup_open(&cgroup, t->pakfire, "pakfire-test", 0));
173
174 // Create jail
175 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
176
177 // Connect jail to the cgroup
178 ASSERT_SUCCESS(pakfire_jail_set_cgroup(jail, cgroup));
179
180 // Set a memory limit of 100 MiB
181 ASSERT_SUCCESS(pakfire_cgroup_set_memory_limit(cgroup, 100 * 1024 * 1024));
182
183 // Try to exhaust all memory
184 ASSERT_FAILURE(pakfire_jail_exec(jail, argv, NULL));
185
186 // Success
187 r = EXIT_SUCCESS;
188
189 FAIL:
190 if (jail)
191 pakfire_jail_unref(jail);
192 if (cgroup) {
193 pakfire_cgroup_destroy(cgroup);
194 pakfire_cgroup_unref(cgroup);
195 }
196
197 return r;
198 }
199
200 static int test_pid_limit(const struct test* t) {
201 struct pakfire_cgroup* cgroup = NULL;
202 struct pakfire_jail* jail = NULL;
203 int r = EXIT_FAILURE;
204
205 const char* argv[] = {
206 "/command", "fork-bomb", NULL,
207 };
208
209 // Create cgroup
210 ASSERT_SUCCESS(pakfire_cgroup_open(&cgroup, t->pakfire, "pakfire-test", 0));
211
212 // Create jail
213 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
214
215 // Connect jail to the cgroup
216 ASSERT_SUCCESS(pakfire_jail_set_cgroup(jail, cgroup));
217
218 // Set a PID limit of 100 processes
219 ASSERT_SUCCESS(pakfire_cgroup_set_pid_limit(cgroup, 100));
220
221 // Try to fork as many processes as possible
222 ASSERT_FAILURE(pakfire_jail_exec(jail, argv, NULL));
223
224 // Success
225 r = EXIT_SUCCESS;
226
227 FAIL:
228 if (jail)
229 pakfire_jail_unref(jail);
230 if (cgroup) {
231 pakfire_cgroup_destroy(cgroup);
232 pakfire_cgroup_unref(cgroup);
233 }
234
235 return r;
236 }
237
238 int main(int argc, const char* argv[]) {
239 testsuite_add_test(test_create);
240 testsuite_add_test(test_env);
241 testsuite_add_test(test_exec);
242 testsuite_add_test(test_launch_into_cgroup);
243 testsuite_add_test(test_nice);
244 testsuite_add_test(test_memory_limit);
245 testsuite_add_test(test_pid_limit);
246
247 return testsuite_run(argc, argv);
248 }