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