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