]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-execute.c
test-execute: change log level from error to notice
[thirdparty/systemd.git] / src / test / test-execute.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
281e05b6
RC
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
cc7fa4fb
RC
21#include <grp.h>
22#include <pwd.h>
ff4ca461 23#include <stdio.h>
70d7aea5 24#include <sys/prctl.h>
ff4ca461 25#include <sys/types.h>
281e05b6 26
4e79aeaa 27#include "cpu-set-util.h"
b4891260 28#include "errno-list.h"
03bd70dd 29#include "fileio.h"
f4f15635 30#include "fs-util.h"
281e05b6 31#include "macro.h"
f4f15635 32#include "manager.h"
281e05b6 33#include "mkdir.h"
ff4ca461 34#include "path-util.h"
c6878637 35#include "rm-rf.h"
349cc4a5 36#if HAVE_SECCOMP
83f12b27
FS
37#include "seccomp-util.h"
38#endif
34b86909 39#include "stat-util.h"
8b3aa503 40#include "test-helper.h"
cc100a5a 41#include "tests.h"
f4f15635 42#include "unit.h"
57c2efa0 43#include "user-util.h"
f4f15635 44#include "util.h"
4dd4cb8f 45#include "virt.h"
281e05b6
RC
46
47typedef void (*test_function_t)(Manager *m);
48
49static void check(Manager *m, Unit *unit, int status_expected, int code_expected) {
50 Service *service = NULL;
51 usec_t ts;
8adb3d63 52 usec_t timeout = 2 * USEC_PER_MINUTE;
281e05b6
RC
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);
ec2ce0c5 61 while (!IN_SET(service->state, SERVICE_DEAD, SERVICE_FAILED)) {
281e05b6
RC
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
57c2efa0
YW
79static 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
119invalid:
120 cache = 0;
121 return false;
122}
123
6086d2da
DP
124static 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
281e05b6
RC
142static 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
f0e018e7
YW
152static 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);
d053b72b 155
f0e018e7 156 test(m, "exec-bindpaths.service", 0, CLD_EXITED);
d053b72b 157
f0e018e7
YW
158 (void) rm_rf("/tmp/test-exec-bindpaths", REMOVE_ROOT|REMOVE_PHYSICAL);
159 (void) rm_rf("/tmp/test-exec-bindreadonlypaths", REMOVE_ROOT|REMOVE_PHYSICAL);
d053b72b
YW
160}
161
4e79aeaa
YW
162static 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
281e05b6
RC
186static 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
c6878637 191 (void) rm_rf("/tmp/test-exec_workingdirectory", REMOVE_ROOT|REMOVE_PHYSICAL);
281e05b6
RC
192}
193
194static void test_exec_personality(Manager *m) {
281e05b6
RC
195#if defined(__x86_64__)
196 test(m, "exec-personality-x86-64.service", 0, CLD_EXITED);
7517f51e
HB
197
198#elif defined(__s390__)
199 test(m, "exec-personality-s390.service", 0, CLD_EXITED);
200
12591863
JS
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
5798eb4c 211#elif defined(__i386__)
7517f51e 212 test(m, "exec-personality-x86.service", 0, CLD_EXITED);
f0e018e7
YW
213#else
214 log_notice("Unknown personality, skipping %s", __func__);
281e05b6
RC
215#endif
216}
217
218static 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
223static 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
232static void test_exec_privatedevices(Manager *m) {
f0e018e7
YW
233 int r;
234
4dd4cb8f 235 if (detect_container() > 0) {
f0e018e7 236 log_notice("Testing in container, skipping %s", __func__);
4dd4cb8f
SM
237 return;
238 }
6086d2da 239 if (!is_inaccessible_available()) {
f0e018e7 240 log_notice("Testing without inaccessible, skipping %s", __func__);
6086d2da
DP
241 return;
242 }
243
281e05b6
RC
244 test(m, "exec-privatedevices-yes.service", 0, CLD_EXITED);
245 test(m, "exec-privatedevices-no.service", 0, CLD_EXITED);
6086d2da 246
0608ba98
ZJS
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) {
5cd33ccc 251 log_notice_errno(r, "Could not find capsh binary, skipping remaining tests in %s: %m", __func__);
6086d2da
DP
252 return;
253 }
254
615a1f4b
DH
255 test(m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED);
256 test(m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED);
625d8769
DH
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);
615a1f4b
DH
259}
260
4982dbcc 261static void test_exec_protectkernelmodules(Manager *m) {
0608ba98
ZJS
262 int r;
263
3ae33295 264 if (detect_container() > 0) {
f0e018e7 265 log_notice("Testing in container, skipping %s", __func__);
3ae33295
DH
266 return;
267 }
6086d2da 268 if (!is_inaccessible_available()) {
f0e018e7 269 log_notice("Testing without inaccessible, skipping %s", __func__);
6086d2da
DP
270 return;
271 }
3ae33295 272
0608ba98
ZJS
273 r = find_binary("capsh", NULL);
274 if (r < 0) {
5cd33ccc 275 log_notice_errno(r, "Skipping %s, could not find capsh binary: %m", __func__);
0608ba98
ZJS
276 return;
277 }
278
3ae33295
DH
279 test(m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED);
280 test(m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED);
4982dbcc 281 test(m, "exec-protectkernelmodules-yes-mount-propagation.service", 0, CLD_EXITED);
3ae33295
DH
282}
283
f78b36f0 284static void test_exec_readonlypaths(Manager *m) {
34b86909 285
f0e018e7
YW
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__);
34b86909 290 return;
f0e018e7 291 }
34b86909 292
f78b36f0 293 test(m, "exec-readonlypaths.service", 0, CLD_EXITED);
cdfbd1fb 294 test(m, "exec-readonlypaths-mount-propagation.service", 0, CLD_EXITED);
23fd04e9 295 test(m, "exec-readonlypaths-with-bindpaths.service", 0, CLD_EXITED);
cdfbd1fb
DH
296}
297
298static void test_exec_readwritepaths(Manager *m) {
34b86909 299
f0e018e7
YW
300 if (path_is_read_only_fs("/") > 0) {
301 log_notice("Root directory is readonly, skipping %s", __func__);
34b86909 302 return;
f0e018e7 303 }
34b86909 304
cdfbd1fb
DH
305 test(m, "exec-readwritepaths-mount-propagation.service", 0, CLD_EXITED);
306}
307
308static void test_exec_inaccessiblepaths(Manager *m) {
34b86909 309
f0e018e7
YW
310 if (!is_inaccessible_available()) {
311 log_notice("Testing without inaccessible, skipping %s", __func__);
34b86909 312 return;
f0e018e7 313 }
34b86909 314
f0e018e7 315 test(m, "exec-inaccessiblepaths-proc.service", 0, CLD_EXITED);
f78b36f0 316
f0e018e7
YW
317 if (path_is_read_only_fs("/") > 0) {
318 log_notice("Root directory is readonly, skipping remaining tests in %s", __func__);
af4af186
EV
319 return;
320 }
321
f0e018e7 322 test(m, "exec-inaccessiblepaths-mount-propagation.service", 0, CLD_EXITED);
c090d74d
TR
323}
324
4cac89bd
YW
325static 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
281e05b6 333static void test_exec_systemcallfilter(Manager *m) {
349cc4a5 334#if HAVE_SECCOMP
f0e018e7
YW
335 if (!is_seccomp_available()) {
336 log_notice("Seccomp not available, skipping %s", __func__);
83f12b27 337 return;
f0e018e7
YW
338 }
339
281e05b6
RC
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);
b4891260
YW
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);
281e05b6
RC
346#endif
347}
348
349static void test_exec_systemcallerrornumber(Manager *m) {
349cc4a5 350#if HAVE_SECCOMP
f0e018e7
YW
351 if (!is_seccomp_available()) {
352 log_notice("Seccomp not available, skipping %s", __func__);
7a18854f 353 return;
f0e018e7
YW
354 }
355
7a18854f
YW
356 test(m, "exec-systemcallerrornumber-name.service", errno_from_name("EACCES"), CLD_EXITED);
357 test(m, "exec-systemcallerrornumber-number.service", 255, CLD_EXITED);
281e05b6
RC
358#endif
359}
360
f0e018e7 361static void test_exec_restrictnamespaces(Manager *m) {
349cc4a5 362#if HAVE_SECCOMP
f0e018e7
YW
363 if (!is_seccomp_available()) {
364 log_notice("Seccomp not available, skipping %s", __func__);
97e60383 365 return;
f0e018e7 366 }
97e60383 367
f0e018e7
YW
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);
97e60383
DH
372#endif
373}
374
f0e018e7 375static void test_exec_systemcallfilter_system(Manager *m) {
349cc4a5 376#if HAVE_SECCOMP
f0e018e7
YW
377 if (!is_seccomp_available()) {
378 log_notice("Seccomp not available, skipping %s", __func__);
83f12b27 379 return;
f0e018e7 380 }
57c2efa0 381
69b07407
YW
382 test(m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED);
383
57c2efa0 384 if (!check_nobody_user_and_group()) {
5cd33ccc 385 log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
57c2efa0
YW
386 return;
387 }
388
69b07407 389 if (!STR_IN_SET(NOBODY_USER_NAME, "nobody", "nfsnobody")) {
5cd33ccc 390 log_notice("Unsupported nobody user name '%s', skipping remaining tests in %s", NOBODY_USER_NAME, __func__);
69b07407
YW
391 return;
392 }
393
394 test(m, "exec-systemcallfilter-system-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
19c0b0b9
RC
395#endif
396}
397
281e05b6 398static void test_exec_user(Manager *m) {
69b07407
YW
399 test(m, "exec-user.service", 0, CLD_EXITED);
400
57c2efa0 401 if (!check_nobody_user_and_group()) {
5cd33ccc 402 log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
57c2efa0
YW
403 return;
404 }
405
69b07407 406 if (!STR_IN_SET(NOBODY_USER_NAME, "nobody", "nfsnobody")) {
5cd33ccc 407 log_notice("Unsupported nobody user name '%s', skipping remaining tests in %s", NOBODY_USER_NAME, __func__);
69b07407
YW
408 return;
409 }
410
411 test(m, "exec-user-" NOBODY_USER_NAME ".service", 0, CLD_EXITED);
281e05b6
RC
412}
413
414static void test_exec_group(Manager *m) {
69b07407
YW
415 test(m, "exec-group.service", 0, CLD_EXITED);
416
57c2efa0 417 if (!check_nobody_user_and_group()) {
5cd33ccc 418 log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
57c2efa0
YW
419 return;
420 }
421
69b07407 422 if (!STR_IN_SET(NOBODY_GROUP_NAME, "nobody", "nfsnobody", "nogroup")) {
5cd33ccc 423 log_notice("Unsupported nobody group name '%s', skipping remaining tests in %s", NOBODY_GROUP_NAME, __func__);
69b07407
YW
424 return;
425 }
426
427 test(m, "exec-group-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
281e05b6
RC
428}
429
f0e018e7 430static void test_exec_supplementarygroups(Manager *m) {
86b838ea 431 test(m, "exec-supplementarygroups.service", 0, CLD_EXITED);
bf9ace96
DH
432 test(m, "exec-supplementarygroups-single-group.service", 0, CLD_EXITED);
433 test(m, "exec-supplementarygroups-single-group-user.service", 0, CLD_EXITED);
50ca7a35
DH
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);
86b838ea
DH
437}
438
f0e018e7 439static void test_exec_dynamicuser(Manager *m) {
2b9ac11e
DH
440 test(m, "exec-dynamicuser-fixeduser.service", 0, CLD_EXITED);
441 test(m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", 0, CLD_EXITED);
5c67067f 442 test(m, "exec-dynamicuser-supplementarygroups.service", 0, CLD_EXITED);
f0e018e7 443 test(m, "exec-dynamicuser-statedir.service", 0, CLD_EXITED);
028f3a7f
YW
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);
2b9ac11e
DH
451}
452
281e05b6
RC
453static 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
03bd70dd
RC
459static 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
f0e018e7 476 (void) unlink("/tmp/test-exec_environmentfile.conf");
03bd70dd
RC
477}
478
4c80d201 479static void test_exec_passenvironment(Manager *m) {
e1abca2e
FB
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 */
4c80d201
FB
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
27c5347c
RC
503static 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
cc3ddc85
RC
508static 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);
69b07407 511 test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
57c2efa0
YW
512
513 if (!check_nobody_user_and_group()) {
5cd33ccc 514 log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
69b07407
YW
515 return;
516 }
517
518 if (!STR_IN_SET(NOBODY_GROUP_NAME, "nobody", "nfsnobody", "nogroup")) {
5cd33ccc 519 log_notice("Unsupported nobody group name '%s', skipping remaining tests in %s", NOBODY_GROUP_NAME, __func__);
57c2efa0
YW
520 return;
521 }
522
69b07407 523 test(m, "exec-runtimedirectory-owner-" NOBODY_GROUP_NAME ".service", 0, CLD_EXITED);
ff4ca461
RC
524}
525
526static void test_exec_capabilityboundingset(Manager *m) {
527 int r;
528
ff4ca461
RC
529 r = find_binary("capsh", NULL);
530 if (r < 0) {
5cd33ccc 531 log_notice_errno(r, "Skipping %s, could not find capsh binary: %m", __func__);
ff4ca461
RC
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);
cc3ddc85
RC
539}
540
b6dc25ee 541static void test_exec_ambientcapabilities(Manager *m) {
70d7aea5
IP
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);
f0e018e7 549 if (r < 0 && IN_SET(errno, EINVAL, EOPNOTSUPP, ENOSYS)) {
5cd33ccc 550 log_notice("Skipping %s, the kernel does not support ambient capabilities", __func__);
f0e018e7
YW
551 return;
552 }
553
b6dc25ee
YW
554 test(m, "exec-ambientcapabilities.service", 0, CLD_EXITED);
555 test(m, "exec-ambientcapabilities-merge.service", 0, CLD_EXITED);
69b07407 556
57c2efa0 557 if (!check_nobody_user_and_group()) {
5cd33ccc 558 log_notice("nobody user/group is not synthesized or may conflict to other entries, skipping remaining tests in %s", __func__);
69b07407
YW
559 return;
560 }
561
562 if (!STR_IN_SET(NOBODY_USER_NAME, "nobody", "nfsnobody")) {
5cd33ccc 563 log_notice("Unsupported nobody user name '%s', skipping remaining tests in %s", NOBODY_USER_NAME, __func__);
57c2efa0
YW
564 return;
565 }
566
b6dc25ee
YW
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);
70d7aea5
IP
569}
570
63447f11
RC
571static void test_exec_privatenetwork(Manager *m) {
572 int r;
573
574 r = find_binary("ip", NULL);
575 if (r < 0) {
5cd33ccc 576 log_notice_errno(r, "Skipping %s, could not find ip binary: %m", __func__);
63447f11
RC
577 return;
578 }
579
580 test(m, "exec-privatenetwork-yes.service", 0, CLD_EXITED);
581}
582
c388dfea
RC
583static 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
a6226758
RC
588static 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
f0e018e7
YW
595static void test_exec_unsetenvironment(Manager *m) {
596 test(m, "exec-unsetenvironment.service", 0, CLD_EXITED);
42cc99d5
LP
597}
598
9672b583
LP
599static void test_exec_specifier(Manager *m) {
600 test(m, "exec-specifier.service", 0, CLD_EXITED);
8b3c4b57 601 test(m, "exec-specifier@foo-bar.service", 0, CLD_EXITED);
f0e018e7 602 test(m, "exec-specifier-interpolation.service", 0, CLD_EXITED);
9672b583
LP
603}
604
f0e018e7
YW
605static 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);
666d7877
LP
608}
609
ea9cfad1
LP
610static int run_tests(UnitFileScope scope, const test_function_t *tests) {
611 const test_function_t *test = NULL;
19c0b0b9
RC
612 Manager *m = NULL;
613 int r;
614
615 assert_se(tests);
616
e0a3da1f 617 r = manager_new(scope, MANAGER_TEST_RUN_MINIMAL, &m);
19c0b0b9 618 if (MANAGER_SKIP_TEST(r)) {
2179fd10 619 log_notice_errno(r, "Skipping test: manager_new: %m");
19c0b0b9
RC
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
281e05b6 633int main(int argc, char *argv[]) {
ac1f08b9 634 _cleanup_(rm_rf_physical_and_freep) char *runtime_dir = NULL;
ea9cfad1 635 static const test_function_t user_tests[] = {
b6dc25ee 636 test_exec_ambientcapabilities,
f0e018e7 637 test_exec_bindpaths,
f0e018e7 638 test_exec_capabilityboundingset,
4e79aeaa 639 test_exec_cpuaffinity,
f0e018e7
YW
640 test_exec_environment,
641 test_exec_environmentfile,
642 test_exec_group,
281e05b6 643 test_exec_ignoresigpipe,
f0e018e7
YW
644 test_exec_inaccessiblepaths,
645 test_exec_ioschedulingclass,
646 test_exec_oomscoreadjust,
647 test_exec_passenvironment,
648 test_exec_personality,
281e05b6 649 test_exec_privatedevices,
f0e018e7
YW
650 test_exec_privatenetwork,
651 test_exec_privatetmp,
4982dbcc 652 test_exec_protectkernelmodules,
f78b36f0 653 test_exec_readonlypaths,
cdfbd1fb 654 test_exec_readwritepaths,
f0e018e7
YW
655 test_exec_restrictnamespaces,
656 test_exec_runtimedirectory,
657 test_exec_standardinput,
658 test_exec_supplementarygroups,
281e05b6 659 test_exec_systemcallerrornumber,
f0e018e7 660 test_exec_systemcallfilter,
4cac89bd 661 test_exec_temporaryfilesystem,
27c5347c 662 test_exec_umask,
f0e018e7
YW
663 test_exec_unsetenvironment,
664 test_exec_user,
665 test_exec_workingdirectory,
281e05b6
RC
666 NULL,
667 };
ea9cfad1 668 static const test_function_t system_tests[] = {
f0e018e7 669 test_exec_dynamicuser,
9672b583 670 test_exec_specifier,
f0e018e7 671 test_exec_systemcallfilter_system,
19c0b0b9
RC
672 NULL,
673 };
281e05b6
RC
674 int r;
675
469830d1 676 log_set_max_level(LOG_DEBUG);
281e05b6
RC
677 log_parse_environment();
678 log_open();
679
2482f88d
LP
680 (void) unsetenv("USER");
681 (void) unsetenv("LOGNAME");
682
607ff5f9
DH
683 /* It is needed otherwise cgroup creation fails */
684 if (getuid() != 0) {
651d47d1 685 puts("Skipping test: not root");
607ff5f9
DH
686 return EXIT_TEST_SKIP;
687 }
688
651d47d1
ZJS
689 r = enter_cgroup_subroot();
690 if (r == -ENOMEDIUM) {
691 puts("Skipping test: cgroupfs not available");
692 return EXIT_TEST_SKIP;
693 }
8c759b33 694
ac1f08b9 695 assert_se(runtime_dir = setup_fake_runtime_dir());
cc100a5a 696 assert_se(set_unit_path(get_testdata_dir("/test-execute")) >= 0);
281e05b6 697
e1abca2e
FB
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
463d0d15 708 r = run_tests(UNIT_FILE_USER, user_tests);
19c0b0b9
RC
709 if (r != 0)
710 return r;
281e05b6 711
463d0d15 712 return run_tests(UNIT_FILE_SYSTEM, system_tests);
281e05b6 713}