]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/test/test-execute.c
test-execute: rename tests for AmbientCapabilities=
[thirdparty/systemd.git] / src / test / test-execute.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3 This file is part of systemd.
4
5 Copyright 2014 Ronny Chevalier
6
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <grp.h>
22 #include <pwd.h>
23 #include <stdio.h>
24 #include <sys/prctl.h>
25 #include <sys/types.h>
26
27 #include "cpu-set-util.h"
28 #include "errno-list.h"
29 #include "fileio.h"
30 #include "fs-util.h"
31 #include "macro.h"
32 #include "manager.h"
33 #include "mkdir.h"
34 #include "path-util.h"
35 #include "rm-rf.h"
36 #if HAVE_SECCOMP
37 #include "seccomp-util.h"
38 #endif
39 #include "stat-util.h"
40 #include "test-helper.h"
41 #include "tests.h"
42 #include "unit.h"
43 #include "user-util.h"
44 #include "util.h"
45 #include "virt.h"
46
47 typedef void (*test_function_t)(Manager *m);
48
49 static void check(Manager *m, Unit *unit, int status_expected, int code_expected) {
50 Service *service = NULL;
51 usec_t ts;
52 usec_t timeout = 2 * USEC_PER_MINUTE;
53
54 assert_se(m);
55 assert_se(unit);
56
57 service = SERVICE(unit);
58 printf("%s\n", unit->id);
59 exec_context_dump(&service->exec_context, stdout, "\t");
60 ts = now(CLOCK_MONOTONIC);
61 while (!IN_SET(service->state, SERVICE_DEAD, SERVICE_FAILED)) {
62 int r;
63 usec_t n;
64
65 r = sd_event_run(m->event, 100 * USEC_PER_MSEC);
66 assert_se(r >= 0);
67
68 n = now(CLOCK_MONOTONIC);
69 if (ts + timeout < n) {
70 log_error("Test timeout when testing %s", unit->id);
71 exit(EXIT_FAILURE);
72 }
73 }
74 exec_status_dump(&service->main_exec_status, stdout, "\t");
75 assert_se(service->main_exec_status.status == status_expected);
76 assert_se(service->main_exec_status.code == code_expected);
77 }
78
79 static bool check_nobody_user_and_group(void) {
80 static int cache = -1;
81 struct passwd *p;
82 struct group *g;
83
84 if (cache >= 0)
85 return !!cache;
86
87 if (!synthesize_nobody())
88 goto invalid;
89
90 p = getpwnam(NOBODY_USER_NAME);
91 if (!p ||
92 !streq(p->pw_name, NOBODY_USER_NAME) ||
93 p->pw_uid != UID_NOBODY ||
94 p->pw_gid != GID_NOBODY)
95 goto invalid;
96
97 p = getpwuid(UID_NOBODY);
98 if (!p ||
99 !streq(p->pw_name, NOBODY_USER_NAME) ||
100 p->pw_uid != UID_NOBODY ||
101 p->pw_gid != GID_NOBODY)
102 goto invalid;
103
104 g = getgrnam(NOBODY_GROUP_NAME);
105 if (!g ||
106 !streq(g->gr_name, NOBODY_GROUP_NAME) ||
107 g->gr_gid != GID_NOBODY)
108 goto invalid;
109
110 g = getgrgid(GID_NOBODY);
111 if (!g ||
112 !streq(g->gr_name, NOBODY_GROUP_NAME) ||
113 g->gr_gid != GID_NOBODY)
114 goto invalid;
115
116 cache = 1;
117 return true;
118
119 invalid:
120 cache = 0;
121 return false;
122 }
123
124 static bool is_inaccessible_available(void) {
125 char *p;
126
127 FOREACH_STRING(p,
128 "/run/systemd/inaccessible/reg",
129 "/run/systemd/inaccessible/dir",
130 "/run/systemd/inaccessible/chr",
131 "/run/systemd/inaccessible/blk",
132 "/run/systemd/inaccessible/fifo",
133 "/run/systemd/inaccessible/sock"
134 ) {
135 if (access(p, F_OK) < 0)
136 return false;
137 }
138
139 return true;
140 }
141
142 static void test(Manager *m, const char *unit_name, int status_expected, int code_expected) {
143 Unit *unit;
144
145 assert_se(unit_name);
146
147 assert_se(manager_load_unit(m, unit_name, NULL, NULL, &unit) >= 0);
148 assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
149 check(m, unit, status_expected, code_expected);
150 }
151
152 static void test_exec_bindpaths(Manager *m) {
153 assert_se(mkdir_p("/tmp/test-exec-bindpaths", 0755) >= 0);
154 assert_se(mkdir_p("/tmp/test-exec-bindreadonlypaths", 0755) >= 0);
155
156 test(m, "exec-bindpaths.service", 0, CLD_EXITED);
157
158 (void) rm_rf("/tmp/test-exec-bindpaths", REMOVE_ROOT|REMOVE_PHYSICAL);
159 (void) rm_rf("/tmp/test-exec-bindreadonlypaths", REMOVE_ROOT|REMOVE_PHYSICAL);
160 }
161
162 static void test_exec_cpuaffinity(Manager *m) {
163 _cleanup_cpu_free_ cpu_set_t *c = NULL;
164 unsigned n;
165
166 assert_se(c = cpu_set_malloc(&n));
167 assert_se(sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0);
168
169 if (CPU_ISSET_S(0, CPU_ALLOC_SIZE(n), c) == 0) {
170 log_notice("Cannot use CPU 0, skipping %s", __func__);
171 return;
172 }
173
174 test(m, "exec-cpuaffinity1.service", 0, CLD_EXITED);
175 test(m, "exec-cpuaffinity2.service", 0, CLD_EXITED);
176
177 if (CPU_ISSET_S(1, CPU_ALLOC_SIZE(n), c) == 0 ||
178 CPU_ISSET_S(2, CPU_ALLOC_SIZE(n), c) == 0) {
179 log_notice("Cannot use CPU 1 or 2, skipping remaining tests in %s", __func__);
180 return;
181 }
182
183 test(m, "exec-cpuaffinity3.service", 0, CLD_EXITED);
184 }
185
186 static void test_exec_workingdirectory(Manager *m) {
187 assert_se(mkdir_p("/tmp/test-exec_workingdirectory", 0755) >= 0);
188
189 test(m, "exec-workingdirectory.service", 0, CLD_EXITED);
190
191 (void) rm_rf("/tmp/test-exec_workingdirectory", REMOVE_ROOT|REMOVE_PHYSICAL);
192 }
193
194 static void test_exec_personality(Manager *m) {
195 #if defined(__x86_64__)
196 test(m, "exec-personality-x86-64.service", 0, CLD_EXITED);
197
198 #elif defined(__s390__)
199 test(m, "exec-personality-s390.service", 0, CLD_EXITED);
200
201 #elif defined(__powerpc64__)
202 # if __BYTE_ORDER == __BIG_ENDIAN
203 test(m, "exec-personality-ppc64.service", 0, CLD_EXITED);
204 # else
205 test(m, "exec-personality-ppc64le.service", 0, CLD_EXITED);
206 # endif
207
208 #elif defined(__aarch64__)
209 test(m, "exec-personality-aarch64.service", 0, CLD_EXITED);
210
211 #elif defined(__i386__)
212 test(m, "exec-personality-x86.service", 0, CLD_EXITED);
213 #else
214 log_notice("Unknown personality, skipping %s", __func__);
215 #endif
216 }
217
218 static void test_exec_ignoresigpipe(Manager *m) {
219 test(m, "exec-ignoresigpipe-yes.service", 0, CLD_EXITED);
220 test(m, "exec-ignoresigpipe-no.service", SIGPIPE, CLD_KILLED);
221 }
222
223 static void test_exec_privatetmp(Manager *m) {
224 assert_se(touch("/tmp/test-exec_privatetmp") >= 0);
225
226 test(m, "exec-privatetmp-yes.service", 0, CLD_EXITED);
227 test(m, "exec-privatetmp-no.service", 0, CLD_EXITED);
228
229 unlink("/tmp/test-exec_privatetmp");
230 }
231
232 static void test_exec_privatedevices(Manager *m) {
233 int r;
234
235 if (detect_container() > 0) {
236 log_notice("Testing in container, skipping %s", __func__);
237 return;
238 }
239 if (!is_inaccessible_available()) {
240 log_notice("Testing without inaccessible, skipping %s", __func__);
241 return;
242 }
243
244 test(m, "exec-privatedevices-yes.service", 0, CLD_EXITED);
245 test(m, "exec-privatedevices-no.service", 0, CLD_EXITED);
246
247 /* We use capsh to test if the capabilities are
248 * properly set, so be sure that it exists */
249 r = find_binary("capsh", NULL);
250 if (r < 0) {
251 log_error_errno(r, "Could not find capsh binary, skipping remaining tests in %s: %m", __func__);
252 return;
253 }
254
255 test(m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED);
256 test(m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED);
257 test(m, "exec-privatedevices-yes-capability-sys-rawio.service", 0, CLD_EXITED);
258 test(m, "exec-privatedevices-no-capability-sys-rawio.service", 0, CLD_EXITED);
259 }
260
261 static void test_exec_protectkernelmodules(Manager *m) {
262 int r;
263
264 if (detect_container() > 0) {
265 log_notice("Testing in container, skipping %s", __func__);
266 return;
267 }
268 if (!is_inaccessible_available()) {
269 log_notice("Testing without inaccessible, skipping %s", __func__);
270 return;
271 }
272
273 r = find_binary("capsh", NULL);
274 if (r < 0) {
275 log_error_errno(r, "Skipping %s, could not find capsh binary: %m", __func__);
276 return;
277 }
278
279 test(m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED);
280 test(m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED);
281 test(m, "exec-protectkernelmodules-yes-mount-propagation.service", 0, CLD_EXITED);
282 }
283
284 static void test_exec_readonlypaths(Manager *m) {
285
286 test(m, "exec-readonlypaths-simple.service", 0, CLD_EXITED);
287
288 if (path_is_read_only_fs("/var") > 0) {
289 log_notice("Directory /var is readonly, skipping remaining tests in %s", __func__);
290 return;
291 }
292
293 test(m, "exec-readonlypaths.service", 0, CLD_EXITED);
294 test(m, "exec-readonlypaths-mount-propagation.service", 0, CLD_EXITED);
295 test(m, "exec-readonlypaths-with-bindpaths.service", 0, CLD_EXITED);
296 }
297
298 static void test_exec_readwritepaths(Manager *m) {
299
300 if (path_is_read_only_fs("/") > 0) {
301 log_notice("Root directory is readonly, skipping %s", __func__);
302 return;
303 }
304
305 test(m, "exec-readwritepaths-mount-propagation.service", 0, CLD_EXITED);
306 }
307
308 static void test_exec_inaccessiblepaths(Manager *m) {
309
310 if (!is_inaccessible_available()) {
311 log_notice("Testing without inaccessible, skipping %s", __func__);
312 return;
313 }
314
315 test(m, "exec-inaccessiblepaths-proc.service", 0, CLD_EXITED);
316
317 if (path_is_read_only_fs("/") > 0) {
318 log_notice("Root directory is readonly, skipping remaining tests in %s", __func__);
319 return;
320 }
321
322 test(m, "exec-inaccessiblepaths-mount-propagation.service", 0, CLD_EXITED);
323 }
324
325 static void test_exec_temporaryfilesystem(Manager *m) {
326
327 test(m, "exec-temporaryfilesystem-options.service", 0, CLD_EXITED);
328 test(m, "exec-temporaryfilesystem-ro.service", 0, CLD_EXITED);
329 test(m, "exec-temporaryfilesystem-rw.service", 0, CLD_EXITED);
330 test(m, "exec-temporaryfilesystem-usr.service", 0, CLD_EXITED);
331 }
332
333 static void test_exec_systemcallfilter(Manager *m) {
334 #if HAVE_SECCOMP
335 if (!is_seccomp_available()) {
336 log_notice("Seccomp not available, skipping %s", __func__);
337 return;
338 }
339
340 test(m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED);
341 test(m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED);
342 test(m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED);
343 test(m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED);
344 test(m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED);
345 test(m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED);
346 #endif
347 }
348
349 static void test_exec_systemcallerrornumber(Manager *m) {
350 #if HAVE_SECCOMP
351 if (!is_seccomp_available()) {
352 log_notice("Seccomp not available, skipping %s", __func__);
353 return;
354 }
355
356 test(m, "exec-systemcallerrornumber-name.service", errno_from_name("EACCES"), CLD_EXITED);
357 test(m, "exec-systemcallerrornumber-number.service", 255, CLD_EXITED);
358 #endif
359 }
360
361 static void test_exec_restrictnamespaces(Manager *m) {
362 #if HAVE_SECCOMP
363 if (!is_seccomp_available()) {
364 log_notice("Seccomp not available, skipping %s", __func__);
365 return;
366 }
367
368 test(m, "exec-restrictnamespaces-no.service", 0, CLD_EXITED);
369 test(m, "exec-restrictnamespaces-yes.service", 1, CLD_EXITED);
370 test(m, "exec-restrictnamespaces-mnt.service", 0, CLD_EXITED);
371 test(m, "exec-restrictnamespaces-mnt-blacklist.service", 1, CLD_EXITED);
372 #endif
373 }
374
375 static void test_exec_systemcallfilter_system(Manager *m) {
376 #if HAVE_SECCOMP
377 if (!is_seccomp_available()) {
378 log_notice("Seccomp not available, skipping %s", __func__);
379 return;
380 }
381
382 test(m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED);
383
384 if (!check_nobody_user_and_group()) {
385 log_error_errno(errno, "nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
386 return;
387 }
388
389 if (!STR_IN_SET(NOBODY_USER_NAME, "nobody", "nfsnobody")) {
390 log_error("Unsupported nobody user name '%s', skipping remaining tests in %s", NOBODY_USER_NAME, __func__);
391 return;
392 }
393
394 test(m, "exec-systemcallfilter-system-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
395 #endif
396 }
397
398 static void test_exec_user(Manager *m) {
399 test(m, "exec-user.service", 0, CLD_EXITED);
400
401 if (!check_nobody_user_and_group()) {
402 log_error_errno(errno, "nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
403 return;
404 }
405
406 if (!STR_IN_SET(NOBODY_USER_NAME, "nobody", "nfsnobody")) {
407 log_error("Unsupported nobody user name '%s', skipping remaining tests in %s", NOBODY_USER_NAME, __func__);
408 return;
409 }
410
411 test(m, "exec-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
412 }
413
414 static void test_exec_group(Manager *m) {
415 test(m, "exec-group.service", 0, CLD_EXITED);
416
417 if (!check_nobody_user_and_group()) {
418 log_error_errno(errno, "nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
419 return;
420 }
421
422 if (!STR_IN_SET(NOBODY_GROUP_NAME, "nobody", "nfsnobody", "nogroup")) {
423 log_error("Unsupported nobody group name '%s', skipping remaining tests in %s", NOBODY_GROUP_NAME, __func__);
424 return;
425 }
426
427 test(m, "exec-group-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
428 }
429
430 static void test_exec_supplementarygroups(Manager *m) {
431 test(m, "exec-supplementarygroups.service", 0, CLD_EXITED);
432 test(m, "exec-supplementarygroups-single-group.service", 0, CLD_EXITED);
433 test(m, "exec-supplementarygroups-single-group-user.service", 0, CLD_EXITED);
434 test(m, "exec-supplementarygroups-multiple-groups-default-group-user.service", 0, CLD_EXITED);
435 test(m, "exec-supplementarygroups-multiple-groups-withgid.service", 0, CLD_EXITED);
436 test(m, "exec-supplementarygroups-multiple-groups-withuid.service", 0, CLD_EXITED);
437 }
438
439 static void test_exec_dynamicuser(Manager *m) {
440 test(m, "exec-dynamicuser-fixeduser.service", 0, CLD_EXITED);
441 test(m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", 0, CLD_EXITED);
442 test(m, "exec-dynamicuser-supplementarygroups.service", 0, CLD_EXITED);
443 test(m, "exec-dynamicuser-statedir.service", 0, CLD_EXITED);
444
445 test(m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED);
446 test(m, "exec-dynamicuser-statedir-migrate-step2.service", 0, CLD_EXITED);
447 (void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
448 (void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
449 (void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
450 (void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
451 }
452
453 static void test_exec_environment(Manager *m) {
454 test(m, "exec-environment.service", 0, CLD_EXITED);
455 test(m, "exec-environment-multiple.service", 0, CLD_EXITED);
456 test(m, "exec-environment-empty.service", 0, CLD_EXITED);
457 }
458
459 static void test_exec_environmentfile(Manager *m) {
460 static const char e[] =
461 "VAR1='word1 word2'\n"
462 "VAR2=word3 \n"
463 "# comment1\n"
464 "\n"
465 "; comment2\n"
466 " ; # comment3\n"
467 "line without an equal\n"
468 "VAR3='$word 5 6'\n";
469 int r;
470
471 r = write_string_file("/tmp/test-exec_environmentfile.conf", e, WRITE_STRING_FILE_CREATE);
472 assert_se(r == 0);
473
474 test(m, "exec-environmentfile.service", 0, CLD_EXITED);
475
476 (void) unlink("/tmp/test-exec_environmentfile.conf");
477 }
478
479 static void test_exec_passenvironment(Manager *m) {
480 /* test-execute runs under MANAGER_USER which, by default, forwards all
481 * variables present in the environment, but only those that are
482 * present _at the time it is created_!
483 *
484 * So these PassEnvironment checks are still expected to work, since we
485 * are ensuring the variables are not present at manager creation (they
486 * are unset explicitly in main) and are only set here.
487 *
488 * This is still a good approximation of how a test for MANAGER_SYSTEM
489 * would work.
490 */
491 assert_se(setenv("VAR1", "word1 word2", 1) == 0);
492 assert_se(setenv("VAR2", "word3", 1) == 0);
493 assert_se(setenv("VAR3", "$word 5 6", 1) == 0);
494 test(m, "exec-passenvironment.service", 0, CLD_EXITED);
495 test(m, "exec-passenvironment-repeated.service", 0, CLD_EXITED);
496 test(m, "exec-passenvironment-empty.service", 0, CLD_EXITED);
497 assert_se(unsetenv("VAR1") == 0);
498 assert_se(unsetenv("VAR2") == 0);
499 assert_se(unsetenv("VAR3") == 0);
500 test(m, "exec-passenvironment-absent.service", 0, CLD_EXITED);
501 }
502
503 static void test_exec_umask(Manager *m) {
504 test(m, "exec-umask-default.service", 0, CLD_EXITED);
505 test(m, "exec-umask-0177.service", 0, CLD_EXITED);
506 }
507
508 static void test_exec_runtimedirectory(Manager *m) {
509 test(m, "exec-runtimedirectory.service", 0, CLD_EXITED);
510 test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
511 test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
512
513 if (!check_nobody_user_and_group()) {
514 log_error_errno(errno, "nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
515 return;
516 }
517
518 if (!STR_IN_SET(NOBODY_GROUP_NAME, "nobody", "nfsnobody", "nogroup")) {
519 log_error("Unsupported nobody group name '%s', skipping remaining tests in %s", NOBODY_GROUP_NAME, __func__);
520 return;
521 }
522
523 test(m, "exec-runtimedirectory-owner-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
524 }
525
526 static void test_exec_capabilityboundingset(Manager *m) {
527 int r;
528
529 r = find_binary("capsh", NULL);
530 if (r < 0) {
531 log_error_errno(r, "Skipping %s, could not find capsh binary: %m", __func__);
532 return;
533 }
534
535 test(m, "exec-capabilityboundingset-simple.service", 0, CLD_EXITED);
536 test(m, "exec-capabilityboundingset-reset.service", 0, CLD_EXITED);
537 test(m, "exec-capabilityboundingset-merge.service", 0, CLD_EXITED);
538 test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
539 }
540
541 static void test_exec_ambientcapabilities(Manager *m) {
542 int r;
543
544 /* Check if the kernel has support for ambient capabilities. Run
545 * the tests only if that's the case. Clearing all ambient
546 * capabilities is fine, since we are expecting them to be unset
547 * in the first place for the tests. */
548 r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
549 if (r < 0 && IN_SET(errno, EINVAL, EOPNOTSUPP, ENOSYS)) {
550 log_error("Skipping %s, the kernel does not support ambient capabilities", __func__);
551 return;
552 }
553
554 test(m, "exec-ambientcapabilities.service", 0, CLD_EXITED);
555 test(m, "exec-ambientcapabilities-merge.service", 0, CLD_EXITED);
556
557 if (!check_nobody_user_and_group()) {
558 log_error_errno(errno, "nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
559 return;
560 }
561
562 if (!STR_IN_SET(NOBODY_USER_NAME, "nobody", "nfsnobody")) {
563 log_error("Unsupported nobody user name '%s', skipping remaining tests in %s", NOBODY_USER_NAME, __func__);
564 return;
565 }
566
567 test(m, "exec-ambientcapabilities-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
568 test(m, "exec-ambientcapabilities-merge-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
569 }
570
571 static void test_exec_privatenetwork(Manager *m) {
572 int r;
573
574 r = find_binary("ip", NULL);
575 if (r < 0) {
576 log_error_errno(r, "Skipping %s, could not find ip binary: %m", __func__);
577 return;
578 }
579
580 test(m, "exec-privatenetwork-yes.service", 0, CLD_EXITED);
581 }
582
583 static void test_exec_oomscoreadjust(Manager *m) {
584 test(m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED);
585 test(m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED);
586 }
587
588 static void test_exec_ioschedulingclass(Manager *m) {
589 test(m, "exec-ioschedulingclass-none.service", 0, CLD_EXITED);
590 test(m, "exec-ioschedulingclass-idle.service", 0, CLD_EXITED);
591 test(m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED);
592 test(m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED);
593 }
594
595 static void test_exec_unsetenvironment(Manager *m) {
596 test(m, "exec-unsetenvironment.service", 0, CLD_EXITED);
597 }
598
599 static void test_exec_specifier(Manager *m) {
600 test(m, "exec-specifier.service", 0, CLD_EXITED);
601 test(m, "exec-specifier@foo-bar.service", 0, CLD_EXITED);
602 test(m, "exec-specifier-interpolation.service", 0, CLD_EXITED);
603 }
604
605 static void test_exec_standardinput(Manager *m) {
606 test(m, "exec-standardinput-data.service", 0, CLD_EXITED);
607 test(m, "exec-standardinput-file.service", 0, CLD_EXITED);
608 }
609
610 static int run_tests(UnitFileScope scope, const test_function_t *tests) {
611 const test_function_t *test = NULL;
612 Manager *m = NULL;
613 int r;
614
615 assert_se(tests);
616
617 r = manager_new(scope, MANAGER_TEST_RUN_MINIMAL, &m);
618 if (MANAGER_SKIP_TEST(r)) {
619 log_notice_errno(r, "Skipping test: manager_new: %m");
620 return EXIT_TEST_SKIP;
621 }
622 assert_se(r >= 0);
623 assert_se(manager_startup(m, NULL, NULL) >= 0);
624
625 for (test = tests; test && *test; test++)
626 (*test)(m);
627
628 manager_free(m);
629
630 return 0;
631 }
632
633 int main(int argc, char *argv[]) {
634 _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
635 static const test_function_t user_tests[] = {
636 test_exec_ambientcapabilities,
637 test_exec_bindpaths,
638 test_exec_capabilityboundingset,
639 test_exec_cpuaffinity,
640 test_exec_environment,
641 test_exec_environmentfile,
642 test_exec_group,
643 test_exec_ignoresigpipe,
644 test_exec_inaccessiblepaths,
645 test_exec_ioschedulingclass,
646 test_exec_oomscoreadjust,
647 test_exec_passenvironment,
648 test_exec_personality,
649 test_exec_privatedevices,
650 test_exec_privatenetwork,
651 test_exec_privatetmp,
652 test_exec_protectkernelmodules,
653 test_exec_readonlypaths,
654 test_exec_readwritepaths,
655 test_exec_restrictnamespaces,
656 test_exec_runtimedirectory,
657 test_exec_standardinput,
658 test_exec_supplementarygroups,
659 test_exec_systemcallerrornumber,
660 test_exec_systemcallfilter,
661 test_exec_temporaryfilesystem,
662 test_exec_umask,
663 test_exec_unsetenvironment,
664 test_exec_user,
665 test_exec_workingdirectory,
666 NULL,
667 };
668 static const test_function_t system_tests[] = {
669 test_exec_dynamicuser,
670 test_exec_specifier,
671 test_exec_systemcallfilter_system,
672 NULL,
673 };
674 int r;
675
676 log_set_max_level(LOG_DEBUG);
677 log_parse_environment();
678 log_open();
679
680 (void) unsetenv("USER");
681 (void) unsetenv("LOGNAME");
682
683 /* It is needed otherwise cgroup creation fails */
684 if (getuid() != 0) {
685 puts("Skipping test: not root");
686 return EXIT_TEST_SKIP;
687 }
688
689 r = enter_cgroup_subroot();
690 if (r == -ENOMEDIUM) {
691 puts("Skipping test: cgroupfs not available");
692 return EXIT_TEST_SKIP;
693 }
694
695 assert_se(runtime_dir = setup_fake_runtime_dir());
696 assert_se(set_unit_path(get_testdata_dir("/test-execute")) >= 0);
697
698 /* Unset VAR1, VAR2 and VAR3 which are used in the PassEnvironment test
699 * cases, otherwise (and if they are present in the environment),
700 * `manager_default_environment` will copy them into the default
701 * environment which is passed to each created job, which will make the
702 * tests that expect those not to be present to fail.
703 */
704 assert_se(unsetenv("VAR1") == 0);
705 assert_se(unsetenv("VAR2") == 0);
706 assert_se(unsetenv("VAR3") == 0);
707
708 r = run_tests(UNIT_FILE_USER, user_tests);
709 if (r != 0)
710 return r;
711
712 return run_tests(UNIT_FILE_SYSTEM, system_tests);
713 }