]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/test/test-execute.c
systemd-sysv-install: avoid using ROOT variable from the environment
[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
LP
42#include "unit.h"
43#include "util.h"
4dd4cb8f 44#include "virt.h"
281e05b6
RC
45
46typedef void (*test_function_t)(Manager *m);
47
48static void check(Manager *m, Unit *unit, int status_expected, int code_expected) {
49 Service *service = NULL;
50 usec_t ts;
8adb3d63 51 usec_t timeout = 2 * USEC_PER_MINUTE;
281e05b6
RC
52
53 assert_se(m);
54 assert_se(unit);
55
56 service = SERVICE(unit);
57 printf("%s\n", unit->id);
58 exec_context_dump(&service->exec_context, stdout, "\t");
59 ts = now(CLOCK_MONOTONIC);
ec2ce0c5 60 while (!IN_SET(service->state, SERVICE_DEAD, SERVICE_FAILED)) {
281e05b6
RC
61 int r;
62 usec_t n;
63
64 r = sd_event_run(m->event, 100 * USEC_PER_MSEC);
65 assert_se(r >= 0);
66
67 n = now(CLOCK_MONOTONIC);
68 if (ts + timeout < n) {
69 log_error("Test timeout when testing %s", unit->id);
70 exit(EXIT_FAILURE);
71 }
72 }
73 exec_status_dump(&service->main_exec_status, stdout, "\t");
74 assert_se(service->main_exec_status.status == status_expected);
75 assert_se(service->main_exec_status.code == code_expected);
76}
77
6086d2da
DP
78static bool is_inaccessible_available(void) {
79 char *p;
80
81 FOREACH_STRING(p,
82 "/run/systemd/inaccessible/reg",
83 "/run/systemd/inaccessible/dir",
84 "/run/systemd/inaccessible/chr",
85 "/run/systemd/inaccessible/blk",
86 "/run/systemd/inaccessible/fifo",
87 "/run/systemd/inaccessible/sock"
88 ) {
89 if (access(p, F_OK) < 0)
90 return false;
91 }
92
93 return true;
94}
95
281e05b6
RC
96static void test(Manager *m, const char *unit_name, int status_expected, int code_expected) {
97 Unit *unit;
98
99 assert_se(unit_name);
100
101 assert_se(manager_load_unit(m, unit_name, NULL, NULL, &unit) >= 0);
102 assert_se(UNIT_VTABLE(unit)->start(unit) >= 0);
103 check(m, unit, status_expected, code_expected);
104}
105
f0e018e7
YW
106static void test_exec_bindpaths(Manager *m) {
107 assert_se(mkdir_p("/tmp/test-exec-bindpaths", 0755) >= 0);
108 assert_se(mkdir_p("/tmp/test-exec-bindreadonlypaths", 0755) >= 0);
d053b72b 109
f0e018e7 110 test(m, "exec-bindpaths.service", 0, CLD_EXITED);
d053b72b 111
f0e018e7
YW
112 (void) rm_rf("/tmp/test-exec-bindpaths", REMOVE_ROOT|REMOVE_PHYSICAL);
113 (void) rm_rf("/tmp/test-exec-bindreadonlypaths", REMOVE_ROOT|REMOVE_PHYSICAL);
d053b72b
YW
114}
115
4e79aeaa
YW
116static void test_exec_cpuaffinity(Manager *m) {
117 _cleanup_cpu_free_ cpu_set_t *c = NULL;
118 unsigned n;
119
120 assert_se(c = cpu_set_malloc(&n));
121 assert_se(sched_getaffinity(0, CPU_ALLOC_SIZE(n), c) >= 0);
122
123 if (CPU_ISSET_S(0, CPU_ALLOC_SIZE(n), c) == 0) {
124 log_notice("Cannot use CPU 0, skipping %s", __func__);
125 return;
126 }
127
128 test(m, "exec-cpuaffinity1.service", 0, CLD_EXITED);
129 test(m, "exec-cpuaffinity2.service", 0, CLD_EXITED);
130
131 if (CPU_ISSET_S(1, CPU_ALLOC_SIZE(n), c) == 0 ||
132 CPU_ISSET_S(2, CPU_ALLOC_SIZE(n), c) == 0) {
133 log_notice("Cannot use CPU 1 or 2, skipping remaining tests in %s", __func__);
134 return;
135 }
136
137 test(m, "exec-cpuaffinity3.service", 0, CLD_EXITED);
138}
139
281e05b6
RC
140static void test_exec_workingdirectory(Manager *m) {
141 assert_se(mkdir_p("/tmp/test-exec_workingdirectory", 0755) >= 0);
142
143 test(m, "exec-workingdirectory.service", 0, CLD_EXITED);
144
c6878637 145 (void) rm_rf("/tmp/test-exec_workingdirectory", REMOVE_ROOT|REMOVE_PHYSICAL);
281e05b6
RC
146}
147
148static void test_exec_personality(Manager *m) {
281e05b6
RC
149#if defined(__x86_64__)
150 test(m, "exec-personality-x86-64.service", 0, CLD_EXITED);
7517f51e
HB
151
152#elif defined(__s390__)
153 test(m, "exec-personality-s390.service", 0, CLD_EXITED);
154
12591863
JS
155#elif defined(__powerpc64__)
156# if __BYTE_ORDER == __BIG_ENDIAN
157 test(m, "exec-personality-ppc64.service", 0, CLD_EXITED);
158# else
159 test(m, "exec-personality-ppc64le.service", 0, CLD_EXITED);
160# endif
161
162#elif defined(__aarch64__)
163 test(m, "exec-personality-aarch64.service", 0, CLD_EXITED);
164
5798eb4c 165#elif defined(__i386__)
7517f51e 166 test(m, "exec-personality-x86.service", 0, CLD_EXITED);
f0e018e7
YW
167#else
168 log_notice("Unknown personality, skipping %s", __func__);
281e05b6
RC
169#endif
170}
171
172static void test_exec_ignoresigpipe(Manager *m) {
173 test(m, "exec-ignoresigpipe-yes.service", 0, CLD_EXITED);
174 test(m, "exec-ignoresigpipe-no.service", SIGPIPE, CLD_KILLED);
175}
176
177static void test_exec_privatetmp(Manager *m) {
178 assert_se(touch("/tmp/test-exec_privatetmp") >= 0);
179
180 test(m, "exec-privatetmp-yes.service", 0, CLD_EXITED);
181 test(m, "exec-privatetmp-no.service", 0, CLD_EXITED);
182
183 unlink("/tmp/test-exec_privatetmp");
184}
185
186static void test_exec_privatedevices(Manager *m) {
f0e018e7
YW
187 int r;
188
4dd4cb8f 189 if (detect_container() > 0) {
f0e018e7 190 log_notice("Testing in container, skipping %s", __func__);
4dd4cb8f
SM
191 return;
192 }
6086d2da 193 if (!is_inaccessible_available()) {
f0e018e7 194 log_notice("Testing without inaccessible, skipping %s", __func__);
6086d2da
DP
195 return;
196 }
197
281e05b6
RC
198 test(m, "exec-privatedevices-yes.service", 0, CLD_EXITED);
199 test(m, "exec-privatedevices-no.service", 0, CLD_EXITED);
6086d2da 200
0608ba98
ZJS
201 /* We use capsh to test if the capabilities are
202 * properly set, so be sure that it exists */
203 r = find_binary("capsh", NULL);
204 if (r < 0) {
f0e018e7 205 log_error_errno(r, "Could not find capsh binary, skipping remaining tests in %s: %m", __func__);
6086d2da
DP
206 return;
207 }
208
615a1f4b
DH
209 test(m, "exec-privatedevices-yes-capability-mknod.service", 0, CLD_EXITED);
210 test(m, "exec-privatedevices-no-capability-mknod.service", 0, CLD_EXITED);
625d8769
DH
211 test(m, "exec-privatedevices-yes-capability-sys-rawio.service", 0, CLD_EXITED);
212 test(m, "exec-privatedevices-no-capability-sys-rawio.service", 0, CLD_EXITED);
615a1f4b
DH
213}
214
4982dbcc 215static void test_exec_protectkernelmodules(Manager *m) {
0608ba98
ZJS
216 int r;
217
3ae33295 218 if (detect_container() > 0) {
f0e018e7 219 log_notice("Testing in container, skipping %s", __func__);
3ae33295
DH
220 return;
221 }
6086d2da 222 if (!is_inaccessible_available()) {
f0e018e7 223 log_notice("Testing without inaccessible, skipping %s", __func__);
6086d2da
DP
224 return;
225 }
3ae33295 226
0608ba98
ZJS
227 r = find_binary("capsh", NULL);
228 if (r < 0) {
229 log_error_errno(r, "Skipping %s, could not find capsh binary: %m", __func__);
230 return;
231 }
232
3ae33295
DH
233 test(m, "exec-protectkernelmodules-no-capabilities.service", 0, CLD_EXITED);
234 test(m, "exec-protectkernelmodules-yes-capabilities.service", 0, CLD_EXITED);
4982dbcc 235 test(m, "exec-protectkernelmodules-yes-mount-propagation.service", 0, CLD_EXITED);
3ae33295
DH
236}
237
f78b36f0 238static void test_exec_readonlypaths(Manager *m) {
34b86909 239
f0e018e7
YW
240 test(m, "exec-readonlypaths-simple.service", 0, CLD_EXITED);
241
242 if (path_is_read_only_fs("/var") > 0) {
243 log_notice("Directory /var is readonly, skipping remaining tests in %s", __func__);
34b86909 244 return;
f0e018e7 245 }
34b86909 246
f78b36f0 247 test(m, "exec-readonlypaths.service", 0, CLD_EXITED);
cdfbd1fb 248 test(m, "exec-readonlypaths-mount-propagation.service", 0, CLD_EXITED);
23fd04e9 249 test(m, "exec-readonlypaths-with-bindpaths.service", 0, CLD_EXITED);
cdfbd1fb
DH
250}
251
252static void test_exec_readwritepaths(Manager *m) {
34b86909 253
f0e018e7
YW
254 if (path_is_read_only_fs("/") > 0) {
255 log_notice("Root directory is readonly, skipping %s", __func__);
34b86909 256 return;
f0e018e7 257 }
34b86909 258
cdfbd1fb
DH
259 test(m, "exec-readwritepaths-mount-propagation.service", 0, CLD_EXITED);
260}
261
262static void test_exec_inaccessiblepaths(Manager *m) {
34b86909 263
f0e018e7
YW
264 if (!is_inaccessible_available()) {
265 log_notice("Testing without inaccessible, skipping %s", __func__);
34b86909 266 return;
f0e018e7 267 }
34b86909 268
f0e018e7 269 test(m, "exec-inaccessiblepaths-proc.service", 0, CLD_EXITED);
f78b36f0 270
f0e018e7
YW
271 if (path_is_read_only_fs("/") > 0) {
272 log_notice("Root directory is readonly, skipping remaining tests in %s", __func__);
af4af186
EV
273 return;
274 }
275
f0e018e7 276 test(m, "exec-inaccessiblepaths-mount-propagation.service", 0, CLD_EXITED);
c090d74d
TR
277}
278
4cac89bd
YW
279static void test_exec_temporaryfilesystem(Manager *m) {
280
281 test(m, "exec-temporaryfilesystem-options.service", 0, CLD_EXITED);
282 test(m, "exec-temporaryfilesystem-ro.service", 0, CLD_EXITED);
283 test(m, "exec-temporaryfilesystem-rw.service", 0, CLD_EXITED);
284 test(m, "exec-temporaryfilesystem-usr.service", 0, CLD_EXITED);
285}
286
281e05b6 287static void test_exec_systemcallfilter(Manager *m) {
349cc4a5 288#if HAVE_SECCOMP
f0e018e7
YW
289 if (!is_seccomp_available()) {
290 log_notice("Seccomp not available, skipping %s", __func__);
83f12b27 291 return;
f0e018e7
YW
292 }
293
281e05b6
RC
294 test(m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED);
295 test(m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED);
296 test(m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED);
297 test(m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED);
b4891260
YW
298 test(m, "exec-systemcallfilter-with-errno-name.service", errno_from_name("EILSEQ"), CLD_EXITED);
299 test(m, "exec-systemcallfilter-with-errno-number.service", 255, CLD_EXITED);
281e05b6
RC
300#endif
301}
302
303static void test_exec_systemcallerrornumber(Manager *m) {
349cc4a5 304#if HAVE_SECCOMP
f0e018e7
YW
305 if (!is_seccomp_available()) {
306 log_notice("Seccomp not available, skipping %s", __func__);
7a18854f 307 return;
f0e018e7
YW
308 }
309
7a18854f
YW
310 test(m, "exec-systemcallerrornumber-name.service", errno_from_name("EACCES"), CLD_EXITED);
311 test(m, "exec-systemcallerrornumber-number.service", 255, CLD_EXITED);
281e05b6
RC
312#endif
313}
314
f0e018e7 315static void test_exec_restrictnamespaces(Manager *m) {
349cc4a5 316#if HAVE_SECCOMP
f0e018e7
YW
317 if (!is_seccomp_available()) {
318 log_notice("Seccomp not available, skipping %s", __func__);
97e60383 319 return;
f0e018e7 320 }
97e60383 321
f0e018e7
YW
322 test(m, "exec-restrictnamespaces-no.service", 0, CLD_EXITED);
323 test(m, "exec-restrictnamespaces-yes.service", 1, CLD_EXITED);
324 test(m, "exec-restrictnamespaces-mnt.service", 0, CLD_EXITED);
325 test(m, "exec-restrictnamespaces-mnt-blacklist.service", 1, CLD_EXITED);
97e60383
DH
326#endif
327}
328
f0e018e7 329static void test_exec_systemcallfilter_system(Manager *m) {
349cc4a5 330#if HAVE_SECCOMP
f0e018e7
YW
331 if (!is_seccomp_available()) {
332 log_notice("Seccomp not available, skipping %s", __func__);
83f12b27 333 return;
f0e018e7 334 }
19c0b0b9
RC
335 if (getpwnam("nobody"))
336 test(m, "exec-systemcallfilter-system-user.service", 0, CLD_EXITED);
50f130c2
RC
337 else if (getpwnam("nfsnobody"))
338 test(m, "exec-systemcallfilter-system-user-nfsnobody.service", 0, CLD_EXITED);
19c0b0b9 339 else
303c0bf8 340 log_error_errno(errno, "Skipping %s, could not find nobody/nfsnobody user: %m", __func__);
19c0b0b9
RC
341#endif
342}
343
281e05b6 344static void test_exec_user(Manager *m) {
cc7fa4fb
RC
345 if (getpwnam("nobody"))
346 test(m, "exec-user.service", 0, CLD_EXITED);
50f130c2
RC
347 else if (getpwnam("nfsnobody"))
348 test(m, "exec-user-nfsnobody.service", 0, CLD_EXITED);
ff4ca461 349 else
303c0bf8 350 log_error_errno(errno, "Skipping %s, could not find nobody/nfsnobody user: %m", __func__);
281e05b6
RC
351}
352
353static void test_exec_group(Manager *m) {
cc7fa4fb
RC
354 if (getgrnam("nobody"))
355 test(m, "exec-group.service", 0, CLD_EXITED);
50f130c2
RC
356 else if (getgrnam("nfsnobody"))
357 test(m, "exec-group-nfsnobody.service", 0, CLD_EXITED);
66d73cc7
LP
358 else if (getgrnam("nogroup"))
359 test(m, "exec-group-nogroup.service", 0, CLD_EXITED);
ff4ca461 360 else
66d73cc7 361 log_error_errno(errno, "Skipping %s, could not find nobody/nfsnobody/nogroup group: %m", __func__);
281e05b6
RC
362}
363
f0e018e7 364static void test_exec_supplementarygroups(Manager *m) {
86b838ea 365 test(m, "exec-supplementarygroups.service", 0, CLD_EXITED);
bf9ace96
DH
366 test(m, "exec-supplementarygroups-single-group.service", 0, CLD_EXITED);
367 test(m, "exec-supplementarygroups-single-group-user.service", 0, CLD_EXITED);
50ca7a35
DH
368 test(m, "exec-supplementarygroups-multiple-groups-default-group-user.service", 0, CLD_EXITED);
369 test(m, "exec-supplementarygroups-multiple-groups-withgid.service", 0, CLD_EXITED);
370 test(m, "exec-supplementarygroups-multiple-groups-withuid.service", 0, CLD_EXITED);
86b838ea
DH
371}
372
f0e018e7 373static void test_exec_dynamicuser(Manager *m) {
2b9ac11e
DH
374 test(m, "exec-dynamicuser-fixeduser.service", 0, CLD_EXITED);
375 test(m, "exec-dynamicuser-fixeduser-one-supplementarygroup.service", 0, CLD_EXITED);
5c67067f 376 test(m, "exec-dynamicuser-supplementarygroups.service", 0, CLD_EXITED);
f0e018e7 377 test(m, "exec-dynamicuser-statedir.service", 0, CLD_EXITED);
028f3a7f
YW
378
379 test(m, "exec-dynamicuser-statedir-migrate-step1.service", 0, CLD_EXITED);
380 test(m, "exec-dynamicuser-statedir-migrate-step2.service", 0, CLD_EXITED);
381 (void) rm_rf("/var/lib/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
382 (void) rm_rf("/var/lib/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
383 (void) rm_rf("/var/lib/private/test-dynamicuser-migrate", REMOVE_ROOT|REMOVE_PHYSICAL);
384 (void) rm_rf("/var/lib/private/test-dynamicuser-migrate2", REMOVE_ROOT|REMOVE_PHYSICAL);
2b9ac11e
DH
385}
386
281e05b6
RC
387static void test_exec_environment(Manager *m) {
388 test(m, "exec-environment.service", 0, CLD_EXITED);
389 test(m, "exec-environment-multiple.service", 0, CLD_EXITED);
390 test(m, "exec-environment-empty.service", 0, CLD_EXITED);
391}
392
03bd70dd
RC
393static void test_exec_environmentfile(Manager *m) {
394 static const char e[] =
395 "VAR1='word1 word2'\n"
396 "VAR2=word3 \n"
397 "# comment1\n"
398 "\n"
399 "; comment2\n"
400 " ; # comment3\n"
401 "line without an equal\n"
402 "VAR3='$word 5 6'\n";
403 int r;
404
405 r = write_string_file("/tmp/test-exec_environmentfile.conf", e, WRITE_STRING_FILE_CREATE);
406 assert_se(r == 0);
407
408 test(m, "exec-environmentfile.service", 0, CLD_EXITED);
409
f0e018e7 410 (void) unlink("/tmp/test-exec_environmentfile.conf");
03bd70dd
RC
411}
412
4c80d201 413static void test_exec_passenvironment(Manager *m) {
e1abca2e
FB
414 /* test-execute runs under MANAGER_USER which, by default, forwards all
415 * variables present in the environment, but only those that are
416 * present _at the time it is created_!
417 *
418 * So these PassEnvironment checks are still expected to work, since we
419 * are ensuring the variables are not present at manager creation (they
420 * are unset explicitly in main) and are only set here.
421 *
422 * This is still a good approximation of how a test for MANAGER_SYSTEM
423 * would work.
424 */
4c80d201
FB
425 assert_se(setenv("VAR1", "word1 word2", 1) == 0);
426 assert_se(setenv("VAR2", "word3", 1) == 0);
427 assert_se(setenv("VAR3", "$word 5 6", 1) == 0);
428 test(m, "exec-passenvironment.service", 0, CLD_EXITED);
429 test(m, "exec-passenvironment-repeated.service", 0, CLD_EXITED);
430 test(m, "exec-passenvironment-empty.service", 0, CLD_EXITED);
431 assert_se(unsetenv("VAR1") == 0);
432 assert_se(unsetenv("VAR2") == 0);
433 assert_se(unsetenv("VAR3") == 0);
434 test(m, "exec-passenvironment-absent.service", 0, CLD_EXITED);
435}
436
27c5347c
RC
437static void test_exec_umask(Manager *m) {
438 test(m, "exec-umask-default.service", 0, CLD_EXITED);
439 test(m, "exec-umask-0177.service", 0, CLD_EXITED);
440}
441
cc3ddc85
RC
442static void test_exec_runtimedirectory(Manager *m) {
443 test(m, "exec-runtimedirectory.service", 0, CLD_EXITED);
444 test(m, "exec-runtimedirectory-mode.service", 0, CLD_EXITED);
cc7fa4fb
RC
445 if (getgrnam("nobody"))
446 test(m, "exec-runtimedirectory-owner.service", 0, CLD_EXITED);
50f130c2
RC
447 else if (getgrnam("nfsnobody"))
448 test(m, "exec-runtimedirectory-owner-nfsnobody.service", 0, CLD_EXITED);
ff4ca461 449 else
303c0bf8 450 log_error_errno(errno, "Skipping %s, could not find nobody/nfsnobody group: %m", __func__);
ff4ca461
RC
451}
452
453static void test_exec_capabilityboundingset(Manager *m) {
454 int r;
455
ff4ca461
RC
456 r = find_binary("capsh", NULL);
457 if (r < 0) {
0608ba98 458 log_error_errno(r, "Skipping %s, could not find capsh binary: %m", __func__);
ff4ca461
RC
459 return;
460 }
461
462 test(m, "exec-capabilityboundingset-simple.service", 0, CLD_EXITED);
463 test(m, "exec-capabilityboundingset-reset.service", 0, CLD_EXITED);
464 test(m, "exec-capabilityboundingset-merge.service", 0, CLD_EXITED);
465 test(m, "exec-capabilityboundingset-invert.service", 0, CLD_EXITED);
cc3ddc85
RC
466}
467
70d7aea5
IP
468static void test_exec_capabilityambientset(Manager *m) {
469 int r;
470
471 /* Check if the kernel has support for ambient capabilities. Run
472 * the tests only if that's the case. Clearing all ambient
473 * capabilities is fine, since we are expecting them to be unset
474 * in the first place for the tests. */
475 r = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);
f0e018e7
YW
476 if (r < 0 && IN_SET(errno, EINVAL, EOPNOTSUPP, ENOSYS)) {
477 log_error("Skipping %s, the kernel does not support ambient capabilities", __func__);
478 return;
479 }
480
481 if (getpwnam("nobody")) {
482 test(m, "exec-capabilityambientset.service", 0, CLD_EXITED);
483 test(m, "exec-capabilityambientset-merge.service", 0, CLD_EXITED);
484 } else if (getpwnam("nfsnobody")) {
485 test(m, "exec-capabilityambientset-nfsnobody.service", 0, CLD_EXITED);
486 test(m, "exec-capabilityambientset-merge-nfsnobody.service", 0, CLD_EXITED);
50f130c2 487 } else
f0e018e7 488 log_error_errno(errno, "Skipping %s, could not find nobody/nfsnobody user: %m", __func__);
70d7aea5
IP
489}
490
63447f11
RC
491static void test_exec_privatenetwork(Manager *m) {
492 int r;
493
494 r = find_binary("ip", NULL);
495 if (r < 0) {
303c0bf8 496 log_error_errno(r, "Skipping %s, could not find ip binary: %m", __func__);
63447f11
RC
497 return;
498 }
499
500 test(m, "exec-privatenetwork-yes.service", 0, CLD_EXITED);
501}
502
c388dfea
RC
503static void test_exec_oomscoreadjust(Manager *m) {
504 test(m, "exec-oomscoreadjust-positive.service", 0, CLD_EXITED);
505 test(m, "exec-oomscoreadjust-negative.service", 0, CLD_EXITED);
506}
507
a6226758
RC
508static void test_exec_ioschedulingclass(Manager *m) {
509 test(m, "exec-ioschedulingclass-none.service", 0, CLD_EXITED);
510 test(m, "exec-ioschedulingclass-idle.service", 0, CLD_EXITED);
511 test(m, "exec-ioschedulingclass-realtime.service", 0, CLD_EXITED);
512 test(m, "exec-ioschedulingclass-best-effort.service", 0, CLD_EXITED);
513}
514
f0e018e7
YW
515static void test_exec_unsetenvironment(Manager *m) {
516 test(m, "exec-unsetenvironment.service", 0, CLD_EXITED);
42cc99d5
LP
517}
518
9672b583
LP
519static void test_exec_specifier(Manager *m) {
520 test(m, "exec-specifier.service", 0, CLD_EXITED);
8b3c4b57 521 test(m, "exec-specifier@foo-bar.service", 0, CLD_EXITED);
f0e018e7 522 test(m, "exec-specifier-interpolation.service", 0, CLD_EXITED);
9672b583
LP
523}
524
f0e018e7
YW
525static void test_exec_standardinput(Manager *m) {
526 test(m, "exec-standardinput-data.service", 0, CLD_EXITED);
527 test(m, "exec-standardinput-file.service", 0, CLD_EXITED);
666d7877
LP
528}
529
ea9cfad1
LP
530static int run_tests(UnitFileScope scope, const test_function_t *tests) {
531 const test_function_t *test = NULL;
19c0b0b9
RC
532 Manager *m = NULL;
533 int r;
534
535 assert_se(tests);
536
e0a3da1f 537 r = manager_new(scope, MANAGER_TEST_RUN_MINIMAL, &m);
19c0b0b9 538 if (MANAGER_SKIP_TEST(r)) {
2179fd10 539 log_notice_errno(r, "Skipping test: manager_new: %m");
19c0b0b9
RC
540 return EXIT_TEST_SKIP;
541 }
542 assert_se(r >= 0);
543 assert_se(manager_startup(m, NULL, NULL) >= 0);
544
545 for (test = tests; test && *test; test++)
546 (*test)(m);
547
548 manager_free(m);
549
550 return 0;
551}
552
281e05b6 553int main(int argc, char *argv[]) {
ea9cfad1 554 static const test_function_t user_tests[] = {
f0e018e7
YW
555 test_exec_bindpaths,
556 test_exec_capabilityambientset,
557 test_exec_capabilityboundingset,
4e79aeaa 558 test_exec_cpuaffinity,
f0e018e7
YW
559 test_exec_environment,
560 test_exec_environmentfile,
561 test_exec_group,
281e05b6 562 test_exec_ignoresigpipe,
f0e018e7
YW
563 test_exec_inaccessiblepaths,
564 test_exec_ioschedulingclass,
565 test_exec_oomscoreadjust,
566 test_exec_passenvironment,
567 test_exec_personality,
281e05b6 568 test_exec_privatedevices,
f0e018e7
YW
569 test_exec_privatenetwork,
570 test_exec_privatetmp,
4982dbcc 571 test_exec_protectkernelmodules,
f78b36f0 572 test_exec_readonlypaths,
cdfbd1fb 573 test_exec_readwritepaths,
f0e018e7
YW
574 test_exec_restrictnamespaces,
575 test_exec_runtimedirectory,
576 test_exec_standardinput,
577 test_exec_supplementarygroups,
281e05b6 578 test_exec_systemcallerrornumber,
f0e018e7 579 test_exec_systemcallfilter,
4cac89bd 580 test_exec_temporaryfilesystem,
27c5347c 581 test_exec_umask,
f0e018e7
YW
582 test_exec_unsetenvironment,
583 test_exec_user,
584 test_exec_workingdirectory,
281e05b6
RC
585 NULL,
586 };
ea9cfad1 587 static const test_function_t system_tests[] = {
f0e018e7 588 test_exec_dynamicuser,
9672b583 589 test_exec_specifier,
f0e018e7 590 test_exec_systemcallfilter_system,
19c0b0b9
RC
591 NULL,
592 };
281e05b6
RC
593 int r;
594
469830d1 595 log_set_max_level(LOG_DEBUG);
281e05b6
RC
596 log_parse_environment();
597 log_open();
598
2482f88d
LP
599 (void) unsetenv("USER");
600 (void) unsetenv("LOGNAME");
601
607ff5f9
DH
602 /* It is needed otherwise cgroup creation fails */
603 if (getuid() != 0) {
651d47d1 604 puts("Skipping test: not root");
607ff5f9
DH
605 return EXIT_TEST_SKIP;
606 }
607
651d47d1
ZJS
608 r = enter_cgroup_subroot();
609 if (r == -ENOMEDIUM) {
610 puts("Skipping test: cgroupfs not available");
611 return EXIT_TEST_SKIP;
612 }
8c759b33 613
cc3ddc85 614 assert_se(setenv("XDG_RUNTIME_DIR", "/tmp/", 1) == 0);
cc100a5a 615 assert_se(set_unit_path(get_testdata_dir("/test-execute")) >= 0);
281e05b6 616
e1abca2e
FB
617 /* Unset VAR1, VAR2 and VAR3 which are used in the PassEnvironment test
618 * cases, otherwise (and if they are present in the environment),
619 * `manager_default_environment` will copy them into the default
620 * environment which is passed to each created job, which will make the
621 * tests that expect those not to be present to fail.
622 */
623 assert_se(unsetenv("VAR1") == 0);
624 assert_se(unsetenv("VAR2") == 0);
625 assert_se(unsetenv("VAR3") == 0);
626
463d0d15 627 r = run_tests(UNIT_FILE_USER, user_tests);
19c0b0b9
RC
628 if (r != 0)
629 return r;
281e05b6 630
463d0d15 631 return run_tests(UNIT_FILE_SYSTEM, system_tests);
281e05b6 632}