mirror of
https://github.com/systemd/systemd.git
synced 2025-03-31 14:50:15 +03:00
tests: add test-execute
add tests for the following directives: - WorkingDirectory - Personality - IgnoreSIGPIPE - PrivateTmp - SystemCallFilter: It makes test/TEST-04-SECCOMP obsolete, so it has been removed. - SystemCallErrorNumber - User - Group - Environment
This commit is contained in:
parent
07aa32e31d
commit
281e05b6cb
1
.gitignore
vendored
1
.gitignore
vendored
@ -174,6 +174,7 @@
|
||||
/test-engine
|
||||
/test-env-replace
|
||||
/test-event
|
||||
/test-execute
|
||||
/test-fdset
|
||||
/test-fileio
|
||||
/test-hashmap
|
||||
|
10
Makefile.am
10
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
|
||||
|
||||
|
178
src/test/test-execute.c
Normal file
178
src/test/test-execute.c
Normal file
@ -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;
|
||||
}
|
@ -1 +0,0 @@
|
||||
../TEST-01-BASIC/Makefile
|
@ -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
|
@ -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 "$@"
|
7
test/exec-environment-empty.service
Normal file
7
test/exec-environment-empty.service
Normal file
@ -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=
|
7
test/exec-environment-multiple.service
Normal file
7
test/exec-environment-multiple.service
Normal file
@ -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"
|
6
test/exec-environment.service
Normal file
6
test/exec-environment.service
Normal file
@ -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"
|
6
test/exec-group.service
Normal file
6
test/exec-group.service
Normal file
@ -0,0 +1,6 @@
|
||||
[Unit]
|
||||
Description=Test for Group
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/sh -c 'exit $(test $(id -n -g) = nobody)'
|
||||
Group=nobody
|
7
test/exec-ignoresigpipe-no.service
Normal file
7
test/exec-ignoresigpipe-no.service
Normal file
@ -0,0 +1,7 @@
|
||||
[Unit]
|
||||
Description=Test for IgnoreSIGPIPE=no
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/sh -c 'kill -PIPE 0'
|
||||
Type=oneshot
|
||||
IgnoreSIGPIPE=no
|
7
test/exec-ignoresigpipe-yes.service
Normal file
7
test/exec-ignoresigpipe-yes.service
Normal file
@ -0,0 +1,7 @@
|
||||
[Unit]
|
||||
Description=Test for IgnoreSIGPIPE=yes
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/sh -c 'kill -PIPE 0'
|
||||
Type=oneshot
|
||||
IgnoreSIGPIPE=yes
|
7
test/exec-personality-x86-64.service
Normal file
7
test/exec-personality-x86-64.service
Normal file
@ -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
|
7
test/exec-personality-x86.service
Normal file
7
test/exec-personality-x86.service
Normal file
@ -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
|
7
test/exec-privatedevices-no.service
Normal file
7
test/exec-privatedevices-no.service
Normal file
@ -0,0 +1,7 @@
|
||||
[Unit]
|
||||
Description=Test for PrivateDev=no
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/sh -c 'exit $(test -c /dev/mem)'
|
||||
Type=oneshot
|
||||
PrivateDevices=no
|
7
test/exec-privatedevices-yes.service
Normal file
7
test/exec-privatedevices-yes.service
Normal file
@ -0,0 +1,7 @@
|
||||
[Unit]
|
||||
Description=Test for PrivateDev=yes
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/sh -c 'exit $(test ! -c /dev/mem)'
|
||||
Type=oneshot
|
||||
PrivateDevices=yes
|
7
test/exec-privatetmp-no.service
Normal file
7
test/exec-privatetmp-no.service
Normal file
@ -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
|
7
test/exec-privatetmp-yes.service
Normal file
7
test/exec-privatetmp-yes.service
Normal file
@ -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
|
7
test/exec-systemcallerrornumber.service
Normal file
7
test/exec-systemcallerrornumber.service
Normal file
@ -0,0 +1,7 @@
|
||||
[Unit]
|
||||
Description=Test for SystemCallErrorNumber
|
||||
|
||||
[Service]
|
||||
ExecStart=/usr/bin/uname -a
|
||||
SystemCallFilter=~uname
|
||||
SystemCallErrorNumber=EACCES
|
@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
Description=Will fail
|
||||
Description=Test for SystemCallFilter
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/echo "This should not be seen"
|
@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
Description=Will fail 2
|
||||
Description=Test for SystemCallFilter
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/echo "This should not be seen"
|
@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
Description=Will not fail
|
||||
Description=Test for SystemCallFilter
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/echo "Foo bar"
|
@ -1,5 +1,5 @@
|
||||
[Unit]
|
||||
Description=Reset SystemCallFilter
|
||||
Description=Test for SystemCallFilter
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/echo "Foo bar"
|
6
test/exec-user.service
Normal file
6
test/exec-user.service
Normal file
@ -0,0 +1,6 @@
|
||||
[Unit]
|
||||
Description=Test for User
|
||||
|
||||
[Service]
|
||||
ExecStart=/bin/sh -c 'exit $(test "$USER" = nobody)'
|
||||
User=nobody
|
7
test/exec-workingdirectory.service
Normal file
7
test/exec-workingdirectory.service
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user