]> git.ipfire.org Git - pakfire.git/blob - tests/libpakfire/jail.c
tests: jail: A fork bomb should also exhaust all memory
[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 const char* cmd_exhaust_memory[] = {
31 "/command", "exhaust-memory", NULL,
32 };
33
34 static const char* cmd_fork_bomb[] = {
35 "/command", "fork-bomb", NULL,
36 };
37
38 static int test_create(const struct test* t) {
39 struct pakfire_jail* jail = NULL;
40
41 // Create a new jail
42 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
43
44 // Destroy it
45 ASSERT_NULL(pakfire_jail_unref(jail));
46
47 // Create an interactive jail
48 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, PAKFIRE_JAIL_INTERACTIVE));
49
50 // Destroy it again
51 ASSERT_NULL(pakfire_jail_unref(jail));
52
53 return EXIT_SUCCESS;
54
55 FAIL:
56 return EXIT_FAILURE;
57 }
58
59 static int test_env(const struct test* t) {
60 struct pakfire_jail* jail = NULL;
61
62 // Create a new jail
63 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
64
65 // Check if the default variables are set
66 ASSERT(pakfire_jail_get_env(jail, "LANG"));
67 ASSERT(pakfire_jail_get_env(jail, "TERM"));
68
69 // Fetch a non-existing environment variable
70 ASSERT_NULL(pakfire_jail_get_env(jail, "VARIABLE"));
71
72 // Set a variable
73 ASSERT_SUCCESS(pakfire_jail_set_env(jail, "VARIABLE", "VALUE"));
74
75 // Read the value back
76 ASSERT_STRING_EQUALS(pakfire_jail_get_env(jail, "VARIABLE"), "VALUE");
77
78 // Destroy it
79 ASSERT_NULL(pakfire_jail_unref(jail));
80
81 return EXIT_SUCCESS;
82
83 FAIL:
84 return EXIT_FAILURE;
85 }
86
87 static int test_exec(const struct test* t) {
88 struct pakfire_jail* jail = NULL;
89
90 // Create a new jail
91 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
92
93 // Try to execute something
94 ASSERT_SUCCESS(pakfire_jail_exec(jail, cmd_hello_world, NULL));
95
96 // Destroy it
97 ASSERT_NULL(pakfire_jail_unref(jail));
98
99 return EXIT_SUCCESS;
100
101 FAIL:
102 return EXIT_FAILURE;
103 }
104
105 static int test_launch_into_cgroup(const struct test* t) {
106 struct pakfire_cgroup* cgroup = NULL;
107 struct pakfire_jail* jail = NULL;
108 int r = EXIT_FAILURE;
109
110 // Create a new cgroup
111 ASSERT_SUCCESS(pakfire_cgroup_open(&cgroup, t->pakfire, "pakfire-test", 0));
112
113 // Create a new jail
114 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
115
116 // Connect jail to the cgroup
117 ASSERT_SUCCESS(pakfire_jail_set_cgroup(jail, cgroup));
118
119 // Run command
120 ASSERT(pakfire_jail_exec(jail, cmd_hello_world, NULL) == 0);
121
122 r = EXIT_SUCCESS;
123
124 FAIL:
125 if (cgroup) {
126 pakfire_cgroup_destroy(cgroup);
127 pakfire_cgroup_unref(cgroup);
128 }
129 if (jail)
130 pakfire_jail_unref(jail);
131
132 return r;
133 }
134
135 static int test_nice(const struct test* t) {
136 struct pakfire_jail* jail = NULL;
137 char* output = NULL;
138 int r = EXIT_FAILURE;
139
140 const char* argv[] = {
141 "/command", "print-nice", NULL,
142 };
143
144 // Create a new jail
145 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
146
147 // Set invalid nice levels
148 ASSERT_ERRNO(pakfire_jail_nice(jail, 100), EINVAL);
149 ASSERT_ERRNO(pakfire_jail_nice(jail, -100), EINVAL);
150
151 // Set something sane
152 ASSERT_SUCCESS(pakfire_jail_nice(jail, 5));
153
154 // Check if the nice level has been set
155 ASSERT_SUCCESS(pakfire_jail_exec(jail, argv, &output));
156 ASSERT_STRING_EQUALS(output, "5\n");
157
158 // Success
159 r = EXIT_SUCCESS;
160
161 FAIL:
162 if (jail)
163 pakfire_jail_unref(jail);
164 if (output)
165 free(output);
166
167 return r;
168 }
169
170 static int test_memory_limit(const struct test* t) {
171 struct pakfire_cgroup* cgroup = NULL;
172 struct pakfire_jail* jail = NULL;
173 int r = EXIT_FAILURE;
174
175
176 // Create cgroup
177 ASSERT_SUCCESS(pakfire_cgroup_open(&cgroup, t->pakfire, "pakfire-test", 0));
178
179 // Create jail
180 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
181
182 // Connect jail to the cgroup
183 ASSERT_SUCCESS(pakfire_jail_set_cgroup(jail, cgroup));
184
185 // Set a memory limit of 100 MiB
186 ASSERT_SUCCESS(pakfire_cgroup_set_memory_limit(cgroup, 100 * 1024 * 1024));
187
188 // Try to exhaust all memory
189 ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_exhaust_memory, NULL));
190
191 // A fork bomb should also exhaust all memory
192 ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_fork_bomb, NULL));
193
194 // Success
195 r = EXIT_SUCCESS;
196
197 FAIL:
198 if (jail)
199 pakfire_jail_unref(jail);
200 if (cgroup) {
201 pakfire_cgroup_destroy(cgroup);
202 pakfire_cgroup_unref(cgroup);
203 }
204
205 return r;
206 }
207
208 static int test_pid_limit(const struct test* t) {
209 struct pakfire_cgroup* cgroup = NULL;
210 struct pakfire_jail* jail = NULL;
211 int r = EXIT_FAILURE;
212
213
214 // Create cgroup
215 ASSERT_SUCCESS(pakfire_cgroup_open(&cgroup, t->pakfire, "pakfire-test", 0));
216
217 // Create jail
218 ASSERT_SUCCESS(pakfire_jail_create(&jail, t->pakfire, 0));
219
220 // Connect jail to the cgroup
221 ASSERT_SUCCESS(pakfire_jail_set_cgroup(jail, cgroup));
222
223 // Set a PID limit of 100 processes
224 ASSERT_SUCCESS(pakfire_cgroup_set_pid_limit(cgroup, 100));
225
226 // Try to fork as many processes as possible
227 ASSERT_FAILURE(pakfire_jail_exec(jail, cmd_fork_bomb, NULL));
228
229 // Success
230 r = EXIT_SUCCESS;
231
232 FAIL:
233 if (jail)
234 pakfire_jail_unref(jail);
235 if (cgroup) {
236 pakfire_cgroup_destroy(cgroup);
237 pakfire_cgroup_unref(cgroup);
238 }
239
240 return r;
241 }
242
243 int main(int argc, const char* argv[]) {
244 testsuite_add_test(test_create);
245 testsuite_add_test(test_env);
246 testsuite_add_test(test_exec);
247 testsuite_add_test(test_launch_into_cgroup);
248 testsuite_add_test(test_nice);
249 testsuite_add_test(test_memory_limit);
250 testsuite_add_test(test_pid_limit);
251
252 return testsuite_run(argc, argv);
253 }