Branch data Line data Source code
1 : : /* SPDX-License-Identifier: LGPL-2.1+ */
2 : :
3 : : #include <grp.h>
4 : : #include <pwd.h>
5 : : #include <stdio.h>
6 : : #include <sys/prctl.h>
7 : : #include <sys/types.h>
8 : :
9 : : #include "capability-util.h"
10 : : #include "cpu-set-util.h"
11 : : #include "errno-list.h"
12 : : #include "fileio.h"
13 : : #include "fs-util.h"
14 : : #include "macro.h"
15 : : #include "manager.h"
16 : : #include "missing_prctl.h"
17 : : #include "mkdir.h"
18 : : #include "path-util.h"
19 : : #include "rm-rf.h"
20 : : #if HAVE_SECCOMP
21 : : #include "seccomp-util.h"
22 : : #endif
23 : : #include "service.h"
24 : : #include "stat-util.h"
25 : : #include "test-helper.h"
26 : : #include "tests.h"
27 : : #include "unit.h"
28 : : #include "user-util.h"
29 : : #include "util.h"
30 : : #include "virt.h"
31 : :
32 : : static bool can_unshare;
33 : :
34 : : typedef void (*test_function_t)(Manager *m);
35 : :
36 : 0 : static int cld_dumped_to_killed(int code) {
37 : : /* Depending on the system, seccomp version, … some signals might result in dumping, others in plain
38 : : * killing. Let's ignore the difference here, and map both cases to CLD_KILLED */
39 [ # # ]: 0 : return code == CLD_DUMPED ? CLD_KILLED : code;
40 : : }
41 : :
42 : 0 : static void wait_for_service_finish(Manager *m, Unit *unit) {
43 : 0 : Service *service = NULL;
44 : : usec_t ts;
45 : 0 : usec_t timeout = 2 * USEC_PER_MINUTE;
46 : :
47 [ # # ]: 0 : assert_se(m);
48 [ # # ]: 0 : assert_se(unit);
49 : :
50 : 0 : service = SERVICE(unit);
51 : 0 : printf("%s\n", unit->id);
52 : 0 : exec_context_dump(&service->exec_context, stdout, "\t");
53 : 0 : ts = now(CLOCK_MONOTONIC);
54 [ # # # # ]: 0 : while (!IN_SET(service->state, SERVICE_DEAD, SERVICE_FAILED)) {
55 : : int r;
56 : : usec_t n;
57 : :
58 : 0 : r = sd_event_run(m->event, 100 * USEC_PER_MSEC);
59 [ # # ]: 0 : assert_se(r >= 0);
60 : :
61 : 0 : n = now(CLOCK_MONOTONIC);
62 [ # # ]: 0 : if (ts + timeout < n) {
63 [ # # ]: 0 : log_error("Test timeout when testing %s", unit->id);
64 : 0 : r = unit_kill(unit, KILL_ALL, SIGKILL, NULL);
65 [ # # ]: 0 : if (r < 0)
66 [ # # ]: 0 : log_error_errno(r, "Failed to kill %s: %m", unit->id);
67 : 0 : exit(EXIT_FAILURE);
68 : : }
69 : : }
70 : 0 : }
71 : :
72 : 0 : static void check_main_result(const char *func, Manager *m, Unit *unit, int status_expected, int code_expected) {
73 : 0 : Service *service = NULL;
74 : :
75 [ # # ]: 0 : assert_se(m);
76 [ # # ]: 0 : assert_se(unit);
77 : :
78 : 0 : wait_for_service_finish(m, unit);
79 : :
80 : 0 : service = SERVICE(unit);
81 : 0 : exec_status_dump(&service->main_exec_status, stdout, "\t");
82 : :
83 [ # # ]: 0 : if (cld_dumped_to_killed(service->main_exec_status.code) != cld_dumped_to_killed(code_expected)) {
84 [ # # ]: 0 : log_error("%s: %s: exit code %d, expected %d",
85 : : func, unit->id,
86 : : service->main_exec_status.code, code_expected);
87 : 0 : abort();
88 : : }
89 : :
90 [ # # ]: 0 : if (service->main_exec_status.status != status_expected) {
91 [ # # ]: 0 : log_error("%s: %s: exit status %d, expected %d",
92 : : func, unit->id,
93 : : service->main_exec_status.status, status_expected);
94 : 0 : abort();
95 : : }
96 : 0 : }
97 : :
98 : 0 : static void check_service_result(const char *func, Manager *m, Unit *unit, ServiceResult result_expected) {
99 : 0 : Service *service = NULL;
100 : :
101 [ # # ]: 0 : assert_se(m);
102 [ # # ]: 0 : assert_se(unit);
103 : :
104 : 0 : wait_for_service_finish(m, unit);
105 : :
106 : 0 : service = SERVICE(unit);
107 : :
108 [ # # ]: 0 : if (service->result != result_expected) {
109 [ # # ]: 0 : log_error("%s: %s: service end result %s, expected %s",
110 : : func, unit->id,
111 : : service_result_to_string(service->result),
112 : : service_result_to_string(result_expected));
113 : 0 : abort();
114 : : }
115 : 0 : }
116 : :
117 : 0 : static bool check_nobody_user_and_group(void) {
118 : : static int cache = -1;
119 : : struct passwd *p;
120 : : struct group *g;
121 : :
122 [ # # ]: 0 : if (cache >= 0)
123 : 0 : return !!cache;
124 : :
125 [ # # ]: 0 : if (!synthesize_nobody())
126 : 0 : goto invalid;
127 : :
128 : 0 : p = getpwnam(NOBODY_USER_NAME);
129 [ # # ]: 0 : if (!p ||
130 [ # # ]: 0 : !streq(p->pw_name, NOBODY_USER_NAME) ||
131 [ # # ]: 0 : p->pw_uid != UID_NOBODY ||
132 [ # # ]: 0 : p->pw_gid != GID_NOBODY)
133 : 0 : goto invalid;
134 : :
135 : 0 : p = getpwuid(UID_NOBODY);
136 [ # # ]: 0 : if (!p ||
137 [ # # ]: 0 : !streq(p->pw_name, NOBODY_USER_NAME) ||
138 [ # # ]: 0 : p->pw_uid != UID_NOBODY ||
139 [ # # ]: 0 : p->pw_gid != GID_NOBODY)
140 : 0 : goto invalid;
141 : :
142 : 0 : g = getgrnam(NOBODY_GROUP_NAME);
143 [ # # ]: 0 : if (!g ||
144 [ # # ]: 0 : !streq(g->gr_name, NOBODY_GROUP_NAME) ||
145 [ # # ]: 0 : g->gr_gid != GID_NOBODY)
146 : 0 : goto invalid;
147 : :
148 : 0 : g = getgrgid(GID_NOBODY);
149 [ # # ]: 0 : if (!g ||
150 [ # # ]: 0 : !streq(g->gr_name, NOBODY_GROUP_NAME) ||
151 [ # # ]: 0 : g->gr_gid != GID_NOBODY)
152 : 0 : goto invalid;
153 : :
154 : 0 : cache = 1;
155 : 0 : return true;
156 : :
157 : 0 : invalid:
158 : 0 : cache = 0;
159 : 0 : return false;
160 : : }
161 : :
162 : 0 : static bool check_user_has_group_with_same_name(const char *name) {
163 : : struct passwd *p;
164 : : struct group *g;
165 : :
166 [ # # ]: 0 : assert(name);
167 : :
168 : 0 : p = getpwnam(name);
169 [ # # ]: 0 : if (!p ||
170 [ # # ]: 0 : !streq(p->pw_name, name))
171 : 0 : return false;
172 : :
173 : 0 : g = getgrgid(p->pw_gid);
174 [ # # ]: 0 : if (!g ||
175 [ # # ]: 0 : !streq(g->gr_name, name))
176 : 0 : return false;
177 : :
178 : 0 : return true;
179 : : }
180 : :
181 : 0 : static bool is_inaccessible_available(void) {
182 : : const char *p;
183 : :
184 [ # # ]: 0 : FOREACH_STRING(p,
185 : : "/run/systemd/inaccessible/reg",
186 : : "/run/systemd/inaccessible/dir",
187 : : "/run/systemd/inaccessible/chr",
188 : : "/run/systemd/inaccessible/blk",
189 : : "/run/systemd/inaccessible/fifo",
190 : : "/run/systemd/inaccessible/sock"
191 : : ) {
192 [ # # ]: 0 : if (access(p, F_OK) < 0)
193 : 0 : return false;
194 : : }
195 : :
196 : 0 : return true;
197 : : }
198 : :
199 : 0 : static void test(const char *func, Manager *m, const char *unit_name, int status_expected, int code_expected) {
200 : : Unit *unit;
201 : :
202 [ # # ]: 0 : assert_se(unit_name);
203 : :
204 [ # # ]: 0 : assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
205 [ # # ]: 0 : assert_se(unit_start(unit) >= 0);
206 : 0 : check_main_result(func, m, unit, status_expected, code_expected);
207 : 0 : }
208 : :
209 : 0 : static void test_service(const char *func, Manager *m, const char *unit_name, ServiceResult result_expected) {
210 : : Unit *unit;
211 : :
212 [ # # ]: 0 : assert_se(unit_name);
213 : :
214 [ # # ]: 0 : assert_se(manager_load_startable_unit_or_warn(m, unit_name, NULL, &unit) >= 0);
215 [ # # ]: 0 : assert_se(unit_start(unit) >= 0);
216 : 0 : check_service_result(func, m, unit, result_expected);
217 : 0 : }
218 : :
219 : 0 : static void test_exec_bindpaths(Manager *m) {
220 [ # # ]: 0 : assert_se(mkdir_p("/tmp/test-exec-bindpaths", 0755) >= 0);
221 [ # # ]: 0 : assert_se(mkdir_p("/tmp/test-exec-bindreadonlypaths", 0755) >= 0);
222 : :
223 [ # # ]: 0 : test(__func__, m, "exec-bindpaths.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
224 : :
225 : 0 : (void) rm_rf("/tmp/test-exec-bindpaths", REMOVE_ROOT|REMOVE_PHYSICAL);
226 : 0 : (void) rm_rf("/tmp/test-exec-bindreadonlypaths", REMOVE_ROOT|REMOVE_PHYSICAL);
227 : 0 : }
228 : :
229 : 0 : static void test_exec_cpuaffinity(Manager *m) {
230 [ # # ]: 0 : _cleanup_(cpu_set_reset) CPUSet c = {};
231 : :
232 [ # # ]: 0 : assert_se(cpu_set_realloc(&c, 8192) >= 0); /* just allocate the maximum possible size */
233 [ # # ]: 0 : assert_se(sched_getaffinity(0, c.allocated, c.set) >= 0);
234 : :
235 [ # # # # : 0 : if (!CPU_ISSET_S(0, c.allocated, c.set)) {
# # ]
236 [ # # ]: 0 : log_notice("Cannot use CPU 0, skipping %s", __func__);
237 : 0 : return;
238 : : }
239 : :
240 : 0 : test(__func__, m, "exec-cpuaffinity1.service", 0, CLD_EXITED);
241 : 0 : test(__func__, m, "exec-cpuaffinity2.service", 0, CLD_EXITED);
242 : :
243 [ # # # # : 0 : if (!CPU_ISSET_S(1, c.allocated, c.set) ||
# # ]
244 [ # # # # : 0 : !CPU_ISSET_S(2, c.allocated, c.set)) {
# # ]
245 [ # # ]: 0 : log_notice("Cannot use CPU 1 or 2, skipping remaining tests in %s", __func__);
246 : 0 : return;
247 : : }
248 : :
249 : 0 : test(__func__, m, "exec-cpuaffinity3.service", 0, CLD_EXITED);
250 : : }
251 : :
252 : 0 : static void test_exec_workingdirectory(Manager *m) {
253 [ # # ]: 0 : assert_se(mkdir_p("/tmp/test-exec_workingdirectory", 0755) >= 0);
254 : :
255 : 0 : test(__func__, m, "exec-workingdirectory.service", 0, CLD_EXITED);
256 : 0 : test(__func__, m, "exec-workingdirectory-trailing-dot.service", 0, CLD_EXITED);
257 : :
258 : 0 : (void) rm_rf("/tmp/test-exec_workingdirectory", REMOVE_ROOT|REMOVE_PHYSICAL);
259 : 0 : }
260 : :
261 : 0 : static void test_exec_personality(Manager *m) {
262 : : #if defined(__x86_64__)
263 : 0 : test(__func__, m, "exec-personality-x86-64.service", 0, CLD_EXITED);
264 : :
265 : : #elif defined(__s390__)
266 : : test(__func__, m, "exec-personality-s390.service", 0, CLD_EXITED);
267 : :
268 : : #elif defined(__powerpc64__)
269 : : # if __BYTE_ORDER == __BIG_ENDIAN
270 : : test(__func__, m, "exec-personality-ppc64.service", 0, CLD_EXITED);
271 : : # else
272 : : test(__func__, m, "exec-personality-ppc64le.service", 0, CLD_EXITED);
273 : : # endif
274 : :
275 : : #elif defined(__aarch64__)
276 : : test(__func__, m, "exec-personality-aarch64.service", 0, CLD_EXITED);
277 : :
278 : : #elif defined(__i386__)
279 : : test(__func__, m, "exec-personality-x86.service", 0, CLD_EXITED);
280 : : #else
281 : : log_notice("Unknown personality, skipping %s", __func__);
282 : : #endif
283 : 0 : }
284 : :
285 : 0 : static void test_exec_ignoresigpipe(Manager *m) {
286 : 0 : test(__func__, m, "exec-ignoresigpipe-yes.service", 0, CLD_EXITED);
287 : 0 : test(__func__, m, "exec-ignoresigpipe-no.service", SIGPIPE, CLD_KILLED);
288 : 0 : }
289 : :
290 : 0 : static void test_exec_privatetmp(Manager *m) {
291 [ # # ]: 0 : assert_se(touch("/tmp/test-exec_privatetmp") >= 0);
292 : :
293 : 0 : test(__func__, m, "exec-privatetmp-yes.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
294 : 0 : test(__func__, m, "exec-privatetmp-no.service", 0, CLD_EXITED);
295 : :
296 : 0 : unlink("/tmp/test-exec_privatetmp");
297 : 0 : }
298 : :
299 : 0 : static void test_exec_privatedevices(Manager *m) {
300 : : int r;
301 : :
302 [ # # ]: 0 : if (detect_container() > 0) {
303 [ # # ]: 0 : log_notice("Testing in container, skipping %s", __func__);
304 : 0 : return;
305 : : }
306 [ # # ]: 0 : if (!is_inaccessible_available()) {
307 [ # # ]: 0 : log_notice("Testing without inaccessible, skipping %s", __func__);
308 : 0 : return;
309 : : }
310 : :
311 : 0 : test(__func__, m, "exec-privatedevices-yes.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
312 : 0 : test(__func__, m, "exec-privatedevices-no.service", 0, CLD_EXITED);
313 : 0 : test(__func__, m, "exec-privatedevices-disabled-by-prefix.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
314 : :
315 : : /* We use capsh to test if the capabilities are
316 : : * properly set, so be sure that it exists */
317 : 0 : r = find_binary("capsh", NULL);
318 [ # # ]: 0 : if (r < 0) {
319 [ # # ]: 0 : log_notice_errno(r, "Could not find capsh binary, skipping remaining tests in %s: %m", __func__);
320 : 0 : return;
321 : : }
322 : :
323 : 0 : test(__func__, m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED);
324 : 0 : test(__func__, m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED);
325 : 0 : test(__func__, m, "exec-privatedevices-yes-capability-sys-rawio.service", 0, CLD_EXITED);
326 : 0 : test(__func__, m, "exec-privatedevices-no-capability-sys-rawio.service", 0, CLD_EXITED);
327 : : }
328 : :
329 : 0 : static void test_exec_protecthome(Manager *m) {
330 [ # # ]: 0 : if (!can_unshare) {
331 [ # # ]: 0 : log_notice("Cannot reliably unshare, skipping %s", __func__);
332 : 0 : return;
333 : : }
334 : :
335 : 0 : test(__func__, m, "exec-protecthome-tmpfs-vs-protectsystem-strict.service", 0, CLD_EXITED);
336 : : }
337 : :
338 : 0 : static void test_exec_protectkernelmodules(Manager *m) {
339 : : int r;
340 : :
341 [ # # ]: 0 : if (detect_container() > 0) {
342 [ # # ]: 0 : log_notice("Testing in container, skipping %s", __func__);
343 : 0 : return;
344 : : }
345 [ # # ]: 0 : if (!is_inaccessible_available()) {
346 [ # # ]: 0 : log_notice("Testing without inaccessible, skipping %s", __func__);
347 : 0 : return;
348 : : }
349 : :
350 : 0 : r = find_binary("capsh", NULL);
351 [ # # ]: 0 : if (r < 0) {
352 [ # # ]: 0 : log_notice_errno(r, "Skipping %s, could not find capsh binary: %m", __func__);
353 : 0 : return;
354 : : }
355 : :
356 : 0 : test(__func__, m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED);
357 : 0 : test(__func__, m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED);
358 : 0 : test(__func__, m, "exec-protectkernelmodules-yes-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
359 : : }
360 : :
361 : 0 : static void test_exec_readonlypaths(Manager *m) {
362 : :
363 : 0 : test(__func__, m, "exec-readonlypaths-simple.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
364 : :
365 [ # # ]: 0 : if (path_is_read_only_fs("/var") > 0) {
366 [ # # ]: 0 : log_notice("Directory /var is readonly, skipping remaining tests in %s", __func__);
367 : 0 : return;
368 : : }
369 : :
370 : 0 : test(__func__, m, "exec-readonlypaths.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
371 [ # # ]: 0 : test(__func__, m, "exec-readonlypaths-with-bindpaths.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
372 : 0 : test(__func__, m, "exec-readonlypaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
373 : : }
374 : :
375 : 0 : static void test_exec_readwritepaths(Manager *m) {
376 : :
377 [ # # ]: 0 : if (path_is_read_only_fs("/") > 0) {
378 [ # # ]: 0 : log_notice("Root directory is readonly, skipping %s", __func__);
379 : 0 : return;
380 : : }
381 : :
382 : 0 : test(__func__, m, "exec-readwritepaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
383 : : }
384 : :
385 : 0 : static void test_exec_inaccessiblepaths(Manager *m) {
386 : :
387 [ # # ]: 0 : if (!is_inaccessible_available()) {
388 [ # # ]: 0 : log_notice("Testing without inaccessible, skipping %s", __func__);
389 : 0 : return;
390 : : }
391 : :
392 : 0 : test(__func__, m, "exec-inaccessiblepaths-sys.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
393 : :
394 [ # # ]: 0 : if (path_is_read_only_fs("/") > 0) {
395 [ # # ]: 0 : log_notice("Root directory is readonly, skipping remaining tests in %s", __func__);
396 : 0 : return;
397 : : }
398 : :
399 : 0 : test(__func__, m, "exec-inaccessiblepaths-mount-propagation.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
400 : : }
401 : :
402 : 0 : static void test_exec_temporaryfilesystem(Manager *m) {
403 : :
404 [ # # ]: 0 : test(__func__, m, "exec-temporaryfilesystem-options.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
405 [ # # ]: 0 : test(__func__, m, "exec-temporaryfilesystem-ro.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
406 [ # # ]: 0 : test(__func__, m, "exec-temporaryfilesystem-rw.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
407 [ # # ]: 0 : test(__func__, m, "exec-temporaryfilesystem-usr.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
408 : 0 : }
409 : :
410 : 0 : static void test_exec_systemcallfilter(Manager *m) {
411 : : #if HAVE_SECCOMP
412 : : int r;
413 : :
414 [ # # ]: 0 : if (!is_seccomp_available()) {
415 [ # # ]: 0 : log_notice("Seccomp not available, skipping %s", __func__);
416 : 0 : return;
417 : : }
418 : :
419 : 0 : test(__func__, m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED);
420 : 0 : test(__func__, m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED);
421 : 0 : test(__func__, m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED);
422 : 0 : test(__func__, m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED);
423 : :
424 : 0 : r = find_binary("python3", NULL);
425 [ # # ]: 0 : if (r < 0) {
426 [ # # ]: 0 : log_notice_errno(r, "Skipping remaining tests in %s, could not find python3 binary: %m", __func__);
427 : 0 : return;
428 : : }
429 : :
430 : 0 : test(__func__, m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED);
431 : 0 : test(__func__, m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED);
432 : 0 : test(__func__, m, "exec-systemcallfilter-with-errno-multi.service", errno_from_name("EILSEQ"), CLD_EXITED);
433 : : #endif
434 : : }
435 : :
436 : 0 : static void test_exec_systemcallerrornumber(Manager *m) {
437 : : #if HAVE_SECCOMP
438 : : int r;
439 : :
440 [ # # ]: 0 : if (!is_seccomp_available()) {
441 [ # # ]: 0 : log_notice("Seccomp not available, skipping %s", __func__);
442 : 0 : return;
443 : : }
444 : :
445 : 0 : r = find_binary("python3", NULL);
446 [ # # ]: 0 : if (r < 0) {
447 [ # # ]: 0 : log_notice_errno(r, "Skipping %s, could not find python3 binary: %m", __func__);
448 : 0 : return;
449 : : }
450 : :
451 : 0 : test(__func__, m, "exec-systemcallerrornumber-name.service", errno_from_name("EACCES"), CLD_EXITED);
452 : 0 : test(__func__, m, "exec-systemcallerrornumber-number.service", 255, CLD_EXITED);
453 : : #endif
454 : : }
455 : :
456 : 0 : static void test_exec_restrictnamespaces(Manager *m) {
457 : : #if HAVE_SECCOMP
458 [ # # ]: 0 : if (!is_seccomp_available()) {
459 [ # # ]: 0 : log_notice("Seccomp not available, skipping %s", __func__);
460 : 0 : return;
461 : : }
462 : :
463 : 0 : test(__func__, m, "exec-restrictnamespaces-no.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
464 : 0 : test(__func__, m, "exec-restrictnamespaces-yes.service", 1, CLD_EXITED);
465 : 0 : test(__func__, m, "exec-restrictnamespaces-mnt.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
466 : 0 : test(__func__, m, "exec-restrictnamespaces-mnt-blacklist.service", 1, CLD_EXITED);
467 : 0 : test(__func__, m, "exec-restrictnamespaces-merge-and.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
468 : 0 : test(__func__, m, "exec-restrictnamespaces-merge-or.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
469 : 0 : test(__func__, m, "exec-restrictnamespaces-merge-all.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
470 : : #endif
471 : : }
472 : :
473 : 0 : static void test_exec_systemcallfilter_system(Manager *m) {
474 : : /* Skip this particular test case when running under ASan, as
475 : : * LSan intermittently segfaults when accessing memory right
476 : : * after the test finishes. Generally, ASan & LSan don't like
477 : : * the seccomp stuff.
478 : : */
479 : : #if HAVE_SECCOMP && !HAS_FEATURE_ADDRESS_SANITIZER
480 [ # # ]: 0 : if (!is_seccomp_available()) {
481 [ # # ]: 0 : log_notice("Seccomp not available, skipping %s", __func__);
482 : 0 : return;
483 : : }
484 : :
485 : 0 : test(__func__, m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED);
486 : :
487 [ # # ]: 0 : if (!check_nobody_user_and_group()) {
488 [ # # ]: 0 : log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
489 : 0 : return;
490 : : }
491 : :
492 [ # # ]: 0 : if (!STR_IN_SET(NOBODY_USER_NAME, "nobody", "nfsnobody")) {
493 [ # # ]: 0 : log_notice("Unsupported nobody user name '%s', skipping remaining tests in %s", NOBODY_USER_NAME, __func__);
494 : 0 : return;
495 : : }
496 : :
497 : 0 : test(__func__, m, "exec-systemcallfilter-system-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
498 : : #endif
499 : : }
500 : :
501 : 0 : static void test_exec_user(Manager *m) {
502 : 0 : test(__func__, m, "exec-user.service", 0, CLD_EXITED);
503 : :
504 [ # # ]: 0 : if (!check_nobody_user_and_group()) {
505 [ # # ]: 0 : log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
506 : 0 : return;
507 : : }
508 : :
509 [ # # ]: 0 : if (!STR_IN_SET(NOBODY_USER_NAME, "nobody", "nfsnobody")) {
510 [ # # ]: 0 : log_notice("Unsupported nobody user name '%s', skipping remaining tests in %s", NOBODY_USER_NAME, __func__);
511 : 0 : return;
512 : : }
513 : :
514 : 0 : test(__func__, m, "exec-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
515 : : }
516 : :
517 : 0 : static void test_exec_group(Manager *m) {
518 : 0 : test(__func__, m, "exec-group.service", 0, CLD_EXITED);
519 : :
520 [ # # ]: 0 : if (!check_nobody_user_and_group()) {
521 [ # # ]: 0 : log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
522 : 0 : return;
523 : : }
524 : :
525 [ # # ]: 0 : if (!STR_IN_SET(NOBODY_GROUP_NAME, "nobody", "nfsnobody", "nogroup")) {
526 [ # # ]: 0 : log_notice("Unsupported nobody group name '%s', skipping remaining tests in %s", NOBODY_GROUP_NAME, __func__);
527 : 0 : return;
528 : : }
529 : :
530 : 0 : test(__func__, m, "exec-group-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
531 : : }
532 : :
533 : 0 : static void test_exec_supplementarygroups(Manager *m) {
534 : 0 : test(__func__, m, "exec-supplementarygroups.service", 0, CLD_EXITED);
535 : 0 : test(__func__, m, "exec-supplementarygroups-single-group.service", 0, CLD_EXITED);
536 : 0 : test(__func__, m, "exec-supplementarygroups-single-group-user.service", 0, CLD_EXITED);
537 : 0 : test(__func__, m, "exec-supplementarygroups-multiple-groups-default-group-user.service", 0, CLD_EXITED);
538 : 0 : test(__func__, m, "exec-supplementarygroups-multiple-groups-withgid.service", 0, CLD_EXITED);
539 : 0 : test(__func__, m, "exec-supplementarygroups-multiple-groups-withuid.service", 0, CLD_EXITED);
540 : 0 : }
541 : :
542 : 0 : static void test_exec_dynamicuser(Manager *m) {
543 : :
544 [ # # ]: 0 : test(__func__, m, "exec-dynamicuser-fixeduser.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
545 [ # # ]: 0 : if (check_user_has_group_with_same_name("adm"))
546 [ # # ]: 0 : test(__func__, m, "exec-dynamicuser-fixeduser-adm.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
547 [ # # ]: 0 : if (check_user_has_group_with_same_name("games"))
548 [ # # ]: 0 : test(__func__, m, "exec-dynamicuser-fixeduser-games.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
549 [ # # ]: 0 : test(__func__, m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
550 [ # # ]: 0 : test(__func__, m, "exec-dynamicuser-supplementarygroups.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
551 [ # # ]: 0 : test(__func__, m, "exec-dynamicuser-statedir.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
552 : :
553 : 0 : (void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
554 : 0 : (void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
555 : 0 : (void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
556 : 0 : (void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
557 : :
558 : 0 : test(__func__, m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED);
559 [ # # ]: 0 : test(__func__, m, "exec-dynamicuser-statedir-migrate-step2.service", can_unshare ? 0 : EXIT_NAMESPACE, CLD_EXITED);
560 : :
561 : 0 : (void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
562 : 0 : (void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
563 : 0 : (void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
564 : 0 : (void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
565 : 0 : }
566 : :
567 : 0 : static void test_exec_environment(Manager *m) {
568 : 0 : test(__func__, m, "exec-environment-no-substitute.service", 0, CLD_EXITED);
569 : 0 : test(__func__, m, "exec-environment.service", 0, CLD_EXITED);
570 : 0 : test(__func__, m, "exec-environment-multiple.service", 0, CLD_EXITED);
571 : 0 : test(__func__, m, "exec-environment-empty.service", 0, CLD_EXITED);
572 : 0 : }
573 : :
574 : 0 : static void test_exec_environmentfile(Manager *m) {
575 : : static const char e[] =
576 : : "VAR1='word1 word2'\n"
577 : : "VAR2=word3 \n"
578 : : "# comment1\n"
579 : : "\n"
580 : : "; comment2\n"
581 : : " ; # comment3\n"
582 : : "line without an equal\n"
583 : : "VAR3='$word 5 6'\n"
584 : : "VAR4='new\nline'\n"
585 : : "VAR5=password\\with\\backslashes";
586 : : int r;
587 : :
588 : 0 : r = write_string_file("/tmp/test-exec_environmentfile.conf", e, WRITE_STRING_FILE_CREATE);
589 [ # # ]: 0 : assert_se(r == 0);
590 : :
591 : 0 : test(__func__, m, "exec-environmentfile.service", 0, CLD_EXITED);
592 : :
593 : 0 : (void) unlink("/tmp/test-exec_environmentfile.conf");
594 : 0 : }
595 : :
596 : 0 : static void test_exec_passenvironment(Manager *m) {
597 : : /* test-execute runs under MANAGER_USER which, by default, forwards all
598 : : * variables present in the environment, but only those that are
599 : : * present _at the time it is created_!
600 : : *
601 : : * So these PassEnvironment checks are still expected to work, since we
602 : : * are ensuring the variables are not present at manager creation (they
603 : : * are unset explicitly in main) and are only set here.
604 : : *
605 : : * This is still a good approximation of how a test for MANAGER_SYSTEM
606 : : * would work.
607 : : */
608 [ # # ]: 0 : assert_se(setenv("VAR1", "word1 word2", 1) == 0);
609 [ # # ]: 0 : assert_se(setenv("VAR2", "word3", 1) == 0);
610 [ # # ]: 0 : assert_se(setenv("VAR3", "$word 5 6", 1) == 0);
611 [ # # ]: 0 : assert_se(setenv("VAR4", "new\nline", 1) == 0);
612 [ # # ]: 0 : assert_se(setenv("VAR5", "passwordwithbackslashes", 1) == 0);
613 : 0 : test(__func__, m, "exec-passenvironment.service", 0, CLD_EXITED);
614 : 0 : test(__func__, m, "exec-passenvironment-repeated.service", 0, CLD_EXITED);
615 : 0 : test(__func__, m, "exec-passenvironment-empty.service", 0, CLD_EXITED);
616 [ # # ]: 0 : assert_se(unsetenv("VAR1") == 0);
617 [ # # ]: 0 : assert_se(unsetenv("VAR2") == 0);
618 [ # # ]: 0 : assert_se(unsetenv("VAR3") == 0);
619 [ # # ]: 0 : assert_se(unsetenv("VAR4") == 0);
620 [ # # ]: 0 : assert_se(unsetenv("VAR5") == 0);
621 : 0 : test(__func__, m, "exec-passenvironment-absent.service", 0, CLD_EXITED);
622 : 0 : }
623 : :
624 : 0 : static void test_exec_umask(Manager *m) {
625 : 0 : test(__func__, m, "exec-umask-default.service", 0, CLD_EXITED);
626 : 0 : test(__func__, m, "exec-umask-0177.service", 0, CLD_EXITED);
627 : 0 : }
628 : :
629 : 0 : static void test_exec_runtimedirectory(Manager *m) {
630 : 0 : test(__func__, m, "exec-runtimedirectory.service", 0, CLD_EXITED);
631 : 0 : test(__func__, m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
632 : 0 : test(__func__, m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
633 : :
634 [ # # ]: 0 : if (!check_nobody_user_and_group()) {
635 [ # # ]: 0 : log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
636 : 0 : return;
637 : : }
638 : :
639 [ # # ]: 0 : if (!STR_IN_SET(NOBODY_GROUP_NAME, "nobody", "nfsnobody", "nogroup")) {
640 [ # # ]: 0 : log_notice("Unsupported nobody group name '%s', skipping remaining tests in %s", NOBODY_GROUP_NAME, __func__);
641 : 0 : return;
642 : : }
643 : :
644 : 0 : test(__func__, m, "exec-runtimedirectory-owner-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
645 : : }
646 : :
647 : 0 : static void test_exec_capabilityboundingset(Manager *m) {
648 : : int r;
649 : :
650 : 0 : r = find_binary("capsh", NULL);
651 [ # # ]: 0 : if (r < 0) {
652 [ # # ]: 0 : log_notice_errno(r, "Skipping %s, could not find capsh binary: %m", __func__);
653 : 0 : return;
654 : : }
655 : :
656 [ # # # # ]: 0 : if (have_effective_cap(CAP_CHOWN) <= 0 ||
657 [ # # ]: 0 : have_effective_cap(CAP_FOWNER) <= 0 ||
658 : 0 : have_effective_cap(CAP_KILL) <= 0) {
659 [ # # ]: 0 : log_notice("Skipping %s, this process does not have enough capabilities", __func__);
660 : 0 : return;
661 : : }
662 : :
663 : 0 : test(__func__, m, "exec-capabilityboundingset-simple.service", 0, CLD_EXITED);
664 : 0 : test(__func__, m, "exec-capabilityboundingset-reset.service", 0, CLD_EXITED);
665 : 0 : test(__func__, m, "exec-capabilityboundingset-merge.service", 0, CLD_EXITED);
666 : 0 : test(__func__, m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
667 : : }
668 : :
669 : 0 : static void test_exec_basic(Manager *m) {
670 : 0 : test(__func__, m, "exec-basic.service", 0, CLD_EXITED);
671 : 0 : }
672 : :
673 : 0 : static void test_exec_ambientcapabilities(Manager *m) {
674 : : int r;
675 : :
676 : : /* Check if the kernel has support for ambient capabilities. Run
677 : : * the tests only if that's the case. Clearing all ambient
678 : : * capabilities is fine, since we are expecting them to be unset
679 : : * in the first place for the tests. */
680 : 0 : r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
681 [ # # # # : 0 : if (r < 0 && IN_SET(errno, EINVAL, EOPNOTSUPP, ENOSYS)) {
# # ]
682 [ # # ]: 0 : log_notice("Skipping %s, the kernel does not support ambient capabilities", __func__);
683 : 0 : return;
684 : : }
685 : :
686 [ # # # # ]: 0 : if (have_effective_cap(CAP_CHOWN) <= 0 ||
687 : 0 : have_effective_cap(CAP_NET_RAW) <= 0) {
688 [ # # ]: 0 : log_notice("Skipping %s, this process does not have enough capabilities", __func__);
689 : 0 : return;
690 : : }
691 : :
692 : 0 : test(__func__, m, "exec-ambientcapabilities.service", 0, CLD_EXITED);
693 : 0 : test(__func__, m, "exec-ambientcapabilities-merge.service", 0, CLD_EXITED);
694 : :
695 [ # # ]: 0 : if (!check_nobody_user_and_group()) {
696 [ # # ]: 0 : log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
697 : 0 : return;
698 : : }
699 : :
700 [ # # ]: 0 : if (!STR_IN_SET(NOBODY_USER_NAME, "nobody", "nfsnobody")) {
701 [ # # ]: 0 : log_notice("Unsupported nobody user name '%s', skipping remaining tests in %s", NOBODY_USER_NAME, __func__);
702 : 0 : return;
703 : : }
704 : :
705 : 0 : test(__func__, m, "exec-ambientcapabilities-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
706 : 0 : test(__func__, m, "exec-ambientcapabilities-merge-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
707 : : }
708 : :
709 : 0 : static void test_exec_privatenetwork(Manager *m) {
710 : : int r;
711 : :
712 : 0 : r = find_binary("ip", NULL);
713 [ # # ]: 0 : if (r < 0) {
714 [ # # ]: 0 : log_notice_errno(r, "Skipping %s, could not find ip binary: %m", __func__);
715 : 0 : return;
716 : : }
717 : :
718 [ # # ]: 0 : test(__func__, m, "exec-privatenetwork-yes.service", can_unshare ? 0 : EXIT_NETWORK, CLD_EXITED);
719 : : }
720 : :
721 : 0 : static void test_exec_oomscoreadjust(Manager *m) {
722 : 0 : test(__func__, m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED);
723 : :
724 [ # # ]: 0 : if (detect_container() > 0) {
725 [ # # ]: 0 : log_notice("Testing in container, skipping remaining tests in %s", __func__);
726 : 0 : return;
727 : : }
728 : 0 : test(__func__, m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED);
729 : : }
730 : :
731 : 0 : static void test_exec_ioschedulingclass(Manager *m) {
732 : 0 : test(__func__, m, "exec-ioschedulingclass-none.service", 0, CLD_EXITED);
733 : 0 : test(__func__, m, "exec-ioschedulingclass-idle.service", 0, CLD_EXITED);
734 : 0 : test(__func__, m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED);
735 : :
736 [ # # ]: 0 : if (detect_container() > 0) {
737 [ # # ]: 0 : log_notice("Testing in container, skipping remaining tests in %s", __func__);
738 : 0 : return;
739 : : }
740 : 0 : test(__func__, m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED);
741 : : }
742 : :
743 : 0 : static void test_exec_unsetenvironment(Manager *m) {
744 : 0 : test(__func__, m, "exec-unsetenvironment.service", 0, CLD_EXITED);
745 : 0 : }
746 : :
747 : 0 : static void test_exec_specifier(Manager *m) {
748 : 0 : test(__func__, m, "exec-specifier.service", 0, CLD_EXITED);
749 : 0 : test(__func__, m, "exec-specifier@foo-bar.service", 0, CLD_EXITED);
750 : 0 : test(__func__, m, "exec-specifier-interpolation.service", 0, CLD_EXITED);
751 : 0 : }
752 : :
753 : 0 : static void test_exec_standardinput(Manager *m) {
754 : 0 : test(__func__, m, "exec-standardinput-data.service", 0, CLD_EXITED);
755 : 0 : test(__func__, m, "exec-standardinput-file.service", 0, CLD_EXITED);
756 : 0 : }
757 : :
758 : 0 : static void test_exec_standardoutput(Manager *m) {
759 : 0 : test(__func__, m, "exec-standardoutput-file.service", 0, CLD_EXITED);
760 : 0 : }
761 : :
762 : 0 : static void test_exec_standardoutput_append(Manager *m) {
763 : 0 : test(__func__, m, "exec-standardoutput-append.service", 0, CLD_EXITED);
764 : 0 : }
765 : :
766 : 0 : static void test_exec_condition(Manager *m) {
767 : 0 : test_service(__func__, m, "exec-condition-failed.service", SERVICE_FAILURE_EXIT_CODE);
768 : 0 : test_service(__func__, m, "exec-condition-skip.service", SERVICE_SKIP_CONDITION);
769 : 0 : }
770 : :
771 : : typedef struct test_entry {
772 : : test_function_t f;
773 : : const char *name;
774 : : } test_entry;
775 : :
776 : : #define entry(x) {x, #x}
777 : :
778 : 0 : static int run_tests(UnitFileScope scope, const test_entry tests[], char **patterns) {
779 : 0 : const test_entry *test = NULL;
780 : 0 : _cleanup_(manager_freep) Manager *m = NULL;
781 : : int r;
782 : :
783 [ # # ]: 0 : assert_se(tests);
784 : :
785 : 0 : r = manager_new(scope, MANAGER_TEST_RUN_BASIC, &m);
786 [ # # # # ]: 0 : if (MANAGER_SKIP_TEST(r))
787 : 0 : return log_tests_skipped_errno(r, "manager_new");
788 [ # # ]: 0 : assert_se(r >= 0);
789 [ # # ]: 0 : assert_se(manager_startup(m, NULL, NULL) >= 0);
790 : :
791 [ # # # # ]: 0 : for (test = tests; test && test->f; test++)
792 [ # # ]: 0 : if (strv_fnmatch_or_empty(patterns, test->name, FNM_NOESCAPE))
793 : 0 : test->f(m);
794 : : else
795 [ # # ]: 0 : log_info("Skipping %s because it does not match any pattern.", test->name);
796 : :
797 : 0 : return 0;
798 : : }
799 : :
800 : 4 : int main(int argc, char *argv[]) {
801 : 4 : _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
802 : 4 : _cleanup_free_ char *test_execute_path = NULL;
803 : :
804 : : static const test_entry user_tests[] = {
805 : : entry(test_exec_basic),
806 : : entry(test_exec_ambientcapabilities),
807 : : entry(test_exec_bindpaths),
808 : : entry(test_exec_capabilityboundingset),
809 : : entry(test_exec_condition),
810 : : entry(test_exec_cpuaffinity),
811 : : entry(test_exec_environment),
812 : : entry(test_exec_environmentfile),
813 : : entry(test_exec_group),
814 : : entry(test_exec_ignoresigpipe),
815 : : entry(test_exec_inaccessiblepaths),
816 : : entry(test_exec_ioschedulingclass),
817 : : entry(test_exec_oomscoreadjust),
818 : : entry(test_exec_passenvironment),
819 : : entry(test_exec_personality),
820 : : entry(test_exec_privatedevices),
821 : : entry(test_exec_privatenetwork),
822 : : entry(test_exec_privatetmp),
823 : : entry(test_exec_protecthome),
824 : : entry(test_exec_protectkernelmodules),
825 : : entry(test_exec_readonlypaths),
826 : : entry(test_exec_readwritepaths),
827 : : entry(test_exec_restrictnamespaces),
828 : : entry(test_exec_runtimedirectory),
829 : : entry(test_exec_standardinput),
830 : : entry(test_exec_standardoutput),
831 : : entry(test_exec_standardoutput_append),
832 : : entry(test_exec_supplementarygroups),
833 : : entry(test_exec_systemcallerrornumber),
834 : : entry(test_exec_systemcallfilter),
835 : : entry(test_exec_temporaryfilesystem),
836 : : entry(test_exec_umask),
837 : : entry(test_exec_unsetenvironment),
838 : : entry(test_exec_user),
839 : : entry(test_exec_workingdirectory),
840 : : {},
841 : : };
842 : : static const test_entry system_tests[] = {
843 : : entry(test_exec_dynamicuser),
844 : : entry(test_exec_specifier),
845 : : entry(test_exec_systemcallfilter_system),
846 : : {},
847 : : };
848 : : int r;
849 : :
850 : 4 : test_setup_logging(LOG_DEBUG);
851 : :
852 : : #if HAS_FEATURE_ADDRESS_SANITIZER
853 : : if (is_run_on_travis_ci()) {
854 : : log_notice("Running on TravisCI under ASan, skipping, see https://github.com/systemd/systemd/issues/10696");
855 : : return EXIT_TEST_SKIP;
856 : : }
857 : : #endif
858 : :
859 : 4 : (void) unsetenv("USER");
860 : 4 : (void) unsetenv("LOGNAME");
861 : 4 : (void) unsetenv("SHELL");
862 : 4 : (void) unsetenv("HOME");
863 : :
864 : 4 : can_unshare = have_namespaces();
865 : :
866 : : /* It is needed otherwise cgroup creation fails */
867 [ + - ]: 4 : if (getuid() != 0)
868 : 4 : return log_tests_skipped("not root");
869 : :
870 : 0 : r = enter_cgroup_subroot();
871 [ # # ]: 0 : if (r == -ENOMEDIUM)
872 : 0 : return log_tests_skipped("cgroupfs not available");
873 : :
874 [ # # ]: 0 : assert_se(runtime_dir = setup_fake_runtime_dir());
875 : 0 : test_execute_path = path_join(get_testdata_dir(), "test-execute");
876 [ # # ]: 0 : assert_se(set_unit_path(test_execute_path) >= 0);
877 : :
878 : : /* Unset VAR1, VAR2 and VAR3 which are used in the PassEnvironment test
879 : : * cases, otherwise (and if they are present in the environment),
880 : : * `manager_default_environment` will copy them into the default
881 : : * environment which is passed to each created job, which will make the
882 : : * tests that expect those not to be present to fail.
883 : : */
884 [ # # ]: 0 : assert_se(unsetenv("VAR1") == 0);
885 [ # # ]: 0 : assert_se(unsetenv("VAR2") == 0);
886 [ # # ]: 0 : assert_se(unsetenv("VAR3") == 0);
887 : :
888 : 0 : r = run_tests(UNIT_FILE_USER, user_tests, argv + 1);
889 [ # # ]: 0 : if (r != 0)
890 : 0 : return r;
891 : :
892 : 0 : r = run_tests(UNIT_FILE_SYSTEM, system_tests, argv + 1);
893 [ # # ]: 0 : if (r != 0)
894 : 0 : return r;
895 : :
896 : : #if HAVE_SECCOMP
897 : : /* The following tests are for 1beab8b0d0ff2d7d1436b52d4a0c3d56dc908962. */
898 [ # # ]: 0 : if (!is_seccomp_available()) {
899 [ # # ]: 0 : log_notice("Seccomp not available, skipping unshare() filtered tests.");
900 : 0 : return 0;
901 : : }
902 : :
903 : 0 : _cleanup_hashmap_free_ Hashmap *s = NULL;
904 [ # # ]: 0 : assert_se(s = hashmap_new(NULL));
905 : 0 : r = seccomp_syscall_resolve_name("unshare");
906 [ # # ]: 0 : assert_se(r != __NR_SCMP_ERROR);
907 [ # # ]: 0 : assert_se(hashmap_put(s, UINT32_TO_PTR(r + 1), INT_TO_PTR(-1)) >= 0);
908 [ # # ]: 0 : assert_se(seccomp_load_syscall_filter_set_raw(SCMP_ACT_ALLOW, s, SCMP_ACT_ERRNO(EOPNOTSUPP), true) >= 0);
909 [ # # ]: 0 : assert_se(unshare(CLONE_NEWNS) < 0);
910 [ # # ]: 0 : assert_se(errno == EOPNOTSUPP);
911 : :
912 : 0 : can_unshare = false;
913 : :
914 : 0 : r = run_tests(UNIT_FILE_USER, user_tests, argv + 1);
915 [ # # ]: 0 : if (r != 0)
916 : 0 : return r;
917 : :
918 : 0 : return run_tests(UNIT_FILE_SYSTEM, system_tests, argv + 1);
919 : : #else
920 : : return 0;
921 : : #endif
922 : : }
|