diff options
25 files changed, 295 insertions, 97 deletions
diff --git a/.gitignore b/.gitignore index a4a236fd8d..2293dedd8e 100644 --- a/.gitignore +++ b/.gitignore @@ -174,6 +174,7 @@ /test-engine /test-env-replace /test-event +/test-execute /test-fdset /test-fileio /test-hashmap diff --git a/Makefile.am b/Makefile.am index 0b32639fae..701666c278 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1350,6 +1350,7 @@ tests += \ test-uid-range \ test-bus-policy \ test-locale-util \ + test-execute \ test-copy EXTRA_DIST += \ @@ -1805,6 +1806,15 @@ test_path_CFLAGS = \ test_path_LDADD = \ libsystemd-core.la +test_execute_SOURCES = \ + src/test/test-execute.c + +test_execute_CFLAGS = \ + $(AM_CFLAGS) + +test_execute_LDADD = \ + libsystemd-core.la + test_strxcpyx_SOURCES = \ src/test/test-strxcpyx.c diff --git a/src/test/test-execute.c b/src/test/test-execute.c new file mode 100644 index 0000000000..85deb27f43 --- /dev/null +++ b/src/test/test-execute.c @@ -0,0 +1,178 @@ +/*** + This file is part of systemd. + + Copyright 2014 Ronny Chevalier + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see <http://www.gnu.org/licenses/>. +***/ + +#include <stdio.h> + +#include "unit.h" +#include "manager.h" +#include "util.h" +#include "macro.h" +#include "strv.h" +#include "mkdir.h" + +typedef void (*test_function_t)(Manager *m); + +static void check(Manager *m, Unit *unit, int status_expected, int code_expected) { + Service *service = NULL; + usec_t ts; + usec_t timeout = 2 * USEC_PER_SEC; + + assert_se(m); + assert_se(unit); + + service = SERVICE(unit); + printf("%s\n", unit->id); + exec_context_dump(&service->exec_context, stdout, "\t"); + ts = now(CLOCK_MONOTONIC); + while (service->state != SERVICE_DEAD && service->state != SERVICE_FAILED) { + int r; + usec_t n; + + r = sd_event_run(m->event, 100 * USEC_PER_MSEC); + assert_se(r >= 0); + + n = now(CLOCK_MONOTONIC); + if (ts + timeout < n) { + log_error("Test timeout when testing %s", unit->id); + exit(EXIT_FAILURE); + } + } + exec_status_dump(&service->main_exec_status, stdout, "\t"); + assert_se(service->main_exec_status.status == status_expected); + assert_se(service->main_exec_status.code == code_expected); +} + +static void test(Manager *m, const char *unit_name, int status_expected, int code_expected) { + Unit *unit; + + assert_se(unit_name); + + assert_se(manager_load_unit(m, unit_name, NULL, NULL, &unit) >= 0); + assert_se(UNIT_VTABLE(unit)->start(unit) >= 0); + check(m, unit, status_expected, code_expected); +} + +static void test_exec_workingdirectory(Manager *m) { + assert_se(mkdir_p("/tmp/test-exec_workingdirectory", 0755) >= 0); + + test(m, "exec-workingdirectory.service", 0, CLD_EXITED); + + rm_rf_dangerous("/tmp/test-exec_workingdirectory", false, true, false); +} + +static void test_exec_personality(Manager *m) { + test(m, "exec-personality-x86.service", 0, CLD_EXITED); + +#if defined(__x86_64__) + test(m, "exec-personality-x86-64.service", 0, CLD_EXITED); +#endif +} + +static void test_exec_ignoresigpipe(Manager *m) { + test(m, "exec-ignoresigpipe-yes.service", 0, CLD_EXITED); + test(m, "exec-ignoresigpipe-no.service", SIGPIPE, CLD_KILLED); +} + +static void test_exec_privatetmp(Manager *m) { + assert_se(touch("/tmp/test-exec_privatetmp") >= 0); + + test(m, "exec-privatetmp-yes.service", 0, CLD_EXITED); + test(m, "exec-privatetmp-no.service", 0, CLD_EXITED); + + unlink("/tmp/test-exec_privatetmp"); +} + +static void test_exec_privatedevices(Manager *m) { + test(m, "exec-privatedevices-yes.service", 0, CLD_EXITED); + test(m, "exec-privatedevices-no.service", 0, CLD_EXITED); +} + +static void test_exec_systemcallfilter(Manager *m) { +#ifdef HAVE_SECCOMP + test(m, "exec-systemcallfilter-not-failing.service", 0, CLD_EXITED); + test(m, "exec-systemcallfilter-not-failing2.service", 0, CLD_EXITED); + test(m, "exec-systemcallfilter-failing.service", SIGSYS, CLD_KILLED); + test(m, "exec-systemcallfilter-failing2.service", SIGSYS, CLD_KILLED); +#endif +} + +static void test_exec_systemcallerrornumber(Manager *m) { +#ifdef HAVE_SECCOMP + test(m, "exec-systemcallerrornumber.service", 1, CLD_EXITED); +#endif +} + +static void test_exec_user(Manager *m) { + test(m, "exec-user.service", 0, CLD_EXITED); +} + +static void test_exec_group(Manager *m) { + test(m, "exec-group.service", 0, CLD_EXITED); +} + +static void test_exec_environment(Manager *m) { + test(m, "exec-environment.service", 0, CLD_EXITED); + test(m, "exec-environment-multiple.service", 0, CLD_EXITED); + test(m, "exec-environment-empty.service", 0, CLD_EXITED); +} + +int main(int argc, char *argv[]) { + test_function_t tests[] = { + test_exec_workingdirectory, + test_exec_personality, + test_exec_ignoresigpipe, + test_exec_privatetmp, + test_exec_privatedevices, + test_exec_systemcallfilter, + test_exec_systemcallerrornumber, + test_exec_user, + test_exec_group, + test_exec_environment, + NULL, + }; + test_function_t *test = NULL; + Manager *m = NULL; + int r; + + log_parse_environment(); + log_open(); + + /* It is needed otherwise cgroup creation fails */ + if (getuid() != 0) { + printf("Skipping test: not root\n"); + return EXIT_TEST_SKIP; + } + + assert_se(set_unit_path(TEST_DIR ":") >= 0); + + r = manager_new(SYSTEMD_USER, true, &m); + if (IN_SET(r, -EPERM, -EACCES, -EADDRINUSE, -EHOSTDOWN, -ENOENT)) { + printf("Skipping test: manager_new: %s", strerror(-r)); + return -EXIT_TEST_SKIP; + } + assert_se(r >= 0); + assert_se(manager_startup(m, NULL, NULL) >= 0); + + for (test = tests; test && *test; test++) + (*test)(m); + + manager_free(m); + + return 0; +} diff --git a/test/TEST-04-SECCOMP/Makefile b/test/TEST-04-SECCOMP/Makefile deleted file mode 120000 index e9f93b1104..0000000000 --- a/test/TEST-04-SECCOMP/Makefile +++ /dev/null @@ -1 +0,0 @@ -../TEST-01-BASIC/Makefile
\ No newline at end of file diff --git a/test/TEST-04-SECCOMP/test-seccomp.sh b/test/TEST-04-SECCOMP/test-seccomp.sh deleted file mode 100755 index 2496190445..0000000000 --- a/test/TEST-04-SECCOMP/test-seccomp.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/bash -x - -systemctl start will-fail.service -systemctl start will-fail2.service -systemctl start will-not-fail.service -systemctl start will-not-fail2.service -systemctl is-failed will-fail.service || exit 1 -systemctl is-failed will-fail2.service || exit 1 -systemctl is-failed will-not-fail.service && exit 1 -systemctl is-failed will-not-fail2.service && exit 1 - -touch /testok -exit 0 diff --git a/test/TEST-04-SECCOMP/test.sh b/test/TEST-04-SECCOMP/test.sh deleted file mode 100755 index a85b50cca2..0000000000 --- a/test/TEST-04-SECCOMP/test.sh +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/bash -# -*- mode: shell-script; indent-tabs-mode: nil; sh-basic-offset: 4; -*- -# ex: ts=8 sw=4 sts=4 et filetype=sh -TEST_DESCRIPTION="seccomp tests" - -. $TEST_BASE_DIR/test-functions - -check_result_qemu() { - ret=1 - mkdir -p $TESTDIR/root - mount ${LOOPDEV}p1 $TESTDIR/root - [[ -e $TESTDIR/root/testok ]] && ret=0 - [[ -f $TESTDIR/root/failed ]] && cp -a $TESTDIR/root/failed $TESTDIR - cp -a $TESTDIR/root/var/log/journal $TESTDIR - umount $TESTDIR/root - [[ -f $TESTDIR/failed ]] && cat $TESTDIR/failed - ls -l $TESTDIR/journal/*/*.journal - test -s $TESTDIR/failed && ret=$(($ret+1)) - return $ret -} - -test_run() { - if run_qemu; then - check_result_qemu || return 1 - else - dwarn "can't run QEMU, skipping" - fi - if check_nspawn; then - run_nspawn - check_result_nspawn || return 1 - else - dwarn "can't run systemd-nspawn, skipping" - fi - return 0 -} - -test_setup() { - create_empty_image - mkdir -p $TESTDIR/root - mount ${LOOPDEV}p1 $TESTDIR/root - - # Create what will eventually be our root filesystem onto an overlay - ( - LOG_LEVEL=5 - eval $(udevadm info --export --query=env --name=${LOOPDEV}p2) - - setup_basic_environment - - # setup the testsuite service - cat >$initdir/etc/systemd/system/testsuite.service <<EOF -[Unit] -Description=Testsuite service -After=multi-user.target - -[Service] -ExecStart=/test-seccomp.sh -Type=oneshot -EOF - - # copy the units used by this test - cp {will-fail,will-fail2,will-not-fail,will-not-fail2}.service \ - $initdir/etc/systemd/system - cp test-seccomp.sh $initdir/ - - setup_testsuite - ) - setup_nspawn_root - - ddebug "umount $TESTDIR/root" - umount $TESTDIR/root -} - -test_cleanup() { - umount $TESTDIR/root 2>/dev/null - [[ $LOOPDEV ]] && losetup -d $LOOPDEV - return 0 -} - -do_test "$@" diff --git a/test/exec-environment-empty.service b/test/exec-environment-empty.service new file mode 100644 index 0000000000..0219ca4fd7 --- /dev/null +++ b/test/exec-environment-empty.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Environment + +[Service] +ExecStart=/bin/sh -c 'exit $(test ! "$VAR1" = "word1 word2") && $(test ! "$VAR2" = word3) && $(test ! "$VAR3" = \'$word 5 6\')' +Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" +Environment= diff --git a/test/exec-environment-multiple.service b/test/exec-environment-multiple.service new file mode 100644 index 0000000000..479005a5d8 --- /dev/null +++ b/test/exec-environment-multiple.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Environment + +[Service] +ExecStart=/bin/sh -c 'exit $(test "$VAR1" = "word1 word2") && $(test "$VAR2" = word3) && $(test "$VAR3" = foobar)' +Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" +Environment="VAR3=foobar" diff --git a/test/exec-environment.service b/test/exec-environment.service new file mode 100644 index 0000000000..4586b4c4a9 --- /dev/null +++ b/test/exec-environment.service @@ -0,0 +1,6 @@ +[Unit] +Description=Test for Environment + +[Service] +ExecStart=/bin/sh -c 'exit $(test "$VAR1" = "word1 word2") && $(test "$VAR2" = word3) && $(test "$VAR3" = \'$word 5 6\')' +Environment="VAR1=word1 word2" VAR2=word3 "VAR3=$word 5 6" diff --git a/test/exec-group.service b/test/exec-group.service new file mode 100644 index 0000000000..1aa04b5bd2 --- /dev/null +++ b/test/exec-group.service @@ -0,0 +1,6 @@ +[Unit] +Description=Test for Group + +[Service] +ExecStart=/bin/sh -c 'exit $(test $(id -n -g) = nobody)' +Group=nobody diff --git a/test/exec-ignoresigpipe-no.service b/test/exec-ignoresigpipe-no.service new file mode 100644 index 0000000000..69b2e9d8a8 --- /dev/null +++ b/test/exec-ignoresigpipe-no.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for IgnoreSIGPIPE=no + +[Service] +ExecStart=/bin/sh -c 'kill -PIPE 0' +Type=oneshot +IgnoreSIGPIPE=no diff --git a/test/exec-ignoresigpipe-yes.service b/test/exec-ignoresigpipe-yes.service new file mode 100644 index 0000000000..877ec8aed0 --- /dev/null +++ b/test/exec-ignoresigpipe-yes.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for IgnoreSIGPIPE=yes + +[Service] +ExecStart=/bin/sh -c 'kill -PIPE 0' +Type=oneshot +IgnoreSIGPIPE=yes diff --git a/test/exec-personality-x86-64.service b/test/exec-personality-x86-64.service new file mode 100644 index 0000000000..5bb5d910d0 --- /dev/null +++ b/test/exec-personality-x86-64.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Personality=x86-64 + +[Service] +ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "x86_64")' +Type=oneshot +Personality=x86-64 diff --git a/test/exec-personality-x86.service b/test/exec-personality-x86.service new file mode 100644 index 0000000000..0b370a6480 --- /dev/null +++ b/test/exec-personality-x86.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for Personality=x86 + +[Service] +ExecStart=/bin/sh -c 'echo $(uname -m); exit $(test $(uname -m) = "i686")' +Type=oneshot +Personality=x86 diff --git a/test/exec-privatedevices-no.service b/test/exec-privatedevices-no.service new file mode 100644 index 0000000000..cf4f275fb6 --- /dev/null +++ b/test/exec-privatedevices-no.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for PrivateDev=no + +[Service] +ExecStart=/bin/sh -c 'exit $(test -c /dev/mem)' +Type=oneshot +PrivateDevices=no diff --git a/test/exec-privatedevices-yes.service b/test/exec-privatedevices-yes.service new file mode 100644 index 0000000000..85b3f4f981 --- /dev/null +++ b/test/exec-privatedevices-yes.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for PrivateDev=yes + +[Service] +ExecStart=/bin/sh -c 'exit $(test ! -c /dev/mem)' +Type=oneshot +PrivateDevices=yes diff --git a/test/exec-privatetmp-no.service b/test/exec-privatetmp-no.service new file mode 100644 index 0000000000..d69e552a63 --- /dev/null +++ b/test/exec-privatetmp-no.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for PrivateTmp=no + +[Service] +ExecStart=/bin/sh -c 'exit $(test -f /tmp/test-exec_privatetmp)' +Type=oneshot +PrivateTmp=no diff --git a/test/exec-privatetmp-yes.service b/test/exec-privatetmp-yes.service new file mode 100644 index 0000000000..881a040b87 --- /dev/null +++ b/test/exec-privatetmp-yes.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for PrivateTmp=yes + +[Service] +ExecStart=/bin/sh -c 'exit $(test ! -f /tmp/test-exec_privatetmp)' +Type=oneshot +PrivateTmp=yes diff --git a/test/exec-systemcallerrornumber.service b/test/exec-systemcallerrornumber.service new file mode 100644 index 0000000000..255a8b231a --- /dev/null +++ b/test/exec-systemcallerrornumber.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for SystemCallErrorNumber + +[Service] +ExecStart=/usr/bin/uname -a +SystemCallFilter=~uname +SystemCallErrorNumber=EACCES diff --git a/test/TEST-04-SECCOMP/will-fail.service b/test/exec-systemcallfilter-failing.service index c4e0be90f2..c6ce9368c9 100644 --- a/test/TEST-04-SECCOMP/will-fail.service +++ b/test/exec-systemcallfilter-failing.service @@ -1,5 +1,5 @@ [Unit] -Description=Will fail +Description=Test for SystemCallFilter [Service] ExecStart=/bin/echo "This should not be seen" diff --git a/test/TEST-04-SECCOMP/will-fail2.service b/test/exec-systemcallfilter-failing2.service index f7f1ae9077..b7f7c2aff9 100644 --- a/test/TEST-04-SECCOMP/will-fail2.service +++ b/test/exec-systemcallfilter-failing2.service @@ -1,5 +1,5 @@ [Unit] -Description=Will fail 2 +Description=Test for SystemCallFilter [Service] ExecStart=/bin/echo "This should not be seen" diff --git a/test/TEST-04-SECCOMP/will-not-fail.service b/test/exec-systemcallfilter-not-failing.service index 5c1b59456e..feb206ab6d 100644 --- a/test/TEST-04-SECCOMP/will-not-fail.service +++ b/test/exec-systemcallfilter-not-failing.service @@ -1,5 +1,5 @@ [Unit] -Description=Will not fail +Description=Test for SystemCallFilter [Service] ExecStart=/bin/echo "Foo bar" diff --git a/test/TEST-04-SECCOMP/will-not-fail2.service b/test/exec-systemcallfilter-not-failing2.service index 2df05e33e8..cca469aa3d 100644 --- a/test/TEST-04-SECCOMP/will-not-fail2.service +++ b/test/exec-systemcallfilter-not-failing2.service @@ -1,5 +1,5 @@ [Unit] -Description=Reset SystemCallFilter +Description=Test for SystemCallFilter [Service] ExecStart=/bin/echo "Foo bar" diff --git a/test/exec-user.service b/test/exec-user.service new file mode 100644 index 0000000000..2ca08ebb42 --- /dev/null +++ b/test/exec-user.service @@ -0,0 +1,6 @@ +[Unit] +Description=Test for User + +[Service] +ExecStart=/bin/sh -c 'exit $(test "$USER" = nobody)' +User=nobody diff --git a/test/exec-workingdirectory.service b/test/exec-workingdirectory.service new file mode 100644 index 0000000000..10855d682a --- /dev/null +++ b/test/exec-workingdirectory.service @@ -0,0 +1,7 @@ +[Unit] +Description=Test for WorkingDirectory + +[Service] +ExecStart=/bin/sh -c 'echo $PWD; exit $(test $PWD = "/tmp/test-exec_workingdirectory")' +Type=oneshot +WorkingDirectory=/tmp/test-exec_workingdirectory |