diff --git a/.vimrc b/.vimrc index d40b57a665..9a512ec6c8 100644 --- a/.vimrc +++ b/.vimrc @@ -17,5 +17,5 @@ set expandtab set makeprg=GCC_COLORS=\ make set tw=79 au BufRead,BufNewFile *.xml set tw=109 shiftwidth=2 smarttab -au FileType sh set tw=80 shiftwidth=4 smarttab +au FileType sh set tw=109 shiftwidth=4 smarttab au FileType c set tw=109 diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 9e5b7772ac..49802d6fdf 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -877,17 +877,15 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_NETWORK_ZONE: { - char *j; + _cleanup_free_ char *j = NULL; j = strjoin("vz-", optarg); if (!j) return log_oom(); - if (!ifname_valid(j)) { - log_error("Network zone name not valid: %s", j); - free(j); - return -EINVAL; - } + if (!ifname_valid(j)) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), + "Network zone name not valid: %s", j); free_and_replace(arg_network_zone, j); diff --git a/test/TEST-13-NSPAWN-SMOKE/Makefile b/test/TEST-13-NSPAWN/Makefile similarity index 100% rename from test/TEST-13-NSPAWN-SMOKE/Makefile rename to test/TEST-13-NSPAWN/Makefile diff --git a/test/TEST-13-NSPAWN-SMOKE/test.sh b/test/TEST-13-NSPAWN/test.sh similarity index 73% rename from test/TEST-13-NSPAWN-SMOKE/test.sh rename to test/TEST-13-NSPAWN/test.sh index f607c2733b..8bf33ceb12 100755 --- a/test/TEST-13-NSPAWN-SMOKE/test.sh +++ b/test/TEST-13-NSPAWN/test.sh @@ -2,14 +2,9 @@ # SPDX-License-Identifier: LGPL-2.1-or-later set -e -TEST_DESCRIPTION="systemd-nspawn smoke test" +TEST_DESCRIPTION="systemd-nspawn tests" IMAGE_NAME="nspawn" TEST_NO_NSPAWN=1 -# The test containers are missing the $BUILD_DIR with the necessary note files -# which generates lots of errors regarding missing coverage. Since fixing this -# would make the test code unnecessarily messy, let's just ignore them, at least -# for now. -IGNORE_MISSING_COVERAGE=yes # shellcheck source=test/test-functions . "${TEST_BASE_DIR:?}/test-functions" diff --git a/test/TEST-29-PORTABLE/test.sh b/test/TEST-29-PORTABLE/test.sh index 7727e7b5ca..d826db6b57 100755 --- a/test/TEST-29-PORTABLE/test.sh +++ b/test/TEST-29-PORTABLE/test.sh @@ -12,19 +12,14 @@ TEST_INSTALL_VERITY_MINIMAL=1 # shellcheck source=test/test-functions . "${TEST_BASE_DIR:?}/test-functions" -# Need loop devices for mounting images test_append_files() { - ( - instmods loop =block - instmods squashfs =squashfs - instmods dm_verity =md - instmods overlay =overlayfs - install_dmevent - generate_module_dependencies - inst_binary mksquashfs - inst_binary unsquashfs - install_verity_minimal - ) + instmods squashfs =squashfs + instmods dm_verity =md + install_dmevent + generate_module_dependencies + inst_binary mksquashfs + inst_binary unsquashfs + install_verity_minimal } do_test "$@" diff --git a/test/TEST-43-PRIVATEUSER-UNPRIV/test.sh b/test/TEST-43-PRIVATEUSER-UNPRIV/test.sh index 6e1a91a649..844c08ab1f 100755 --- a/test/TEST-43-PRIVATEUSER-UNPRIV/test.sh +++ b/test/TEST-43-PRIVATEUSER-UNPRIV/test.sh @@ -12,12 +12,8 @@ has_user_dbus_socket || exit 0 command -v mksquashfs >/dev/null 2>&1 || exit 0 test_append_files() { - ( - instmods overlay =overlayfs - generate_module_dependencies - inst_binary unsquashfs - install_verity_minimal - ) + inst_binary unsquashfs + install_verity_minimal } do_test "$@" diff --git a/test/TEST-50-DISSECT/test.sh b/test/TEST-50-DISSECT/test.sh index 276dd7c716..2d44ca2b6e 100755 --- a/test/TEST-50-DISSECT/test.sh +++ b/test/TEST-50-DISSECT/test.sh @@ -16,22 +16,17 @@ command -v mksquashfs >/dev/null 2>&1 || exit 0 command -v veritysetup >/dev/null 2>&1 || exit 0 command -v sfdisk >/dev/null 2>&1 || exit 0 -# Need loop devices for systemd-dissect test_append_files() { - ( - instmods loop =block - instmods squashfs =squashfs - instmods dm_verity =md - instmods overlay =overlayfs - install_dmevent - generate_module_dependencies - inst_binary wc - inst_binary sha256sum - if command -v openssl >/dev/null 2>&1; then - inst_binary openssl - fi - install_verity_minimal - ) + instmods squashfs =squashfs + instmods dm_verity =md + install_dmevent + generate_module_dependencies + inst_binary wc + inst_binary sha256sum + if command -v openssl >/dev/null 2>&1; then + inst_binary openssl + fi + install_verity_minimal } do_test "$@" diff --git a/test/create-busybox-container b/test/create-busybox-container index 73d8066cc6..5b2c80e2c6 100755 --- a/test/create-busybox-container +++ b/test/create-busybox-container @@ -6,30 +6,48 @@ set -o pipefail root="${1:?Usage: $0 container-root}" mkdir -p "$root" -mkdir "$root/bin" +mkdir -p "$root/usr/bin" # On openSUSE the static linked version of busybox is named "busybox-static". busybox="$(type -P busybox-static || type -P busybox)" -cp "$busybox" "$root/bin/busybox" +cp "$busybox" "$root/usr/bin/busybox" +mkdir "$root/var" mkdir -p "$root/usr/lib" touch "$root/usr/lib/os-release" -ln -s busybox "$root/bin/cat" -ln -s busybox "$root/bin/ip" -ln -s busybox "$root/bin/md5sum" -ln -s busybox "$root/bin/ps" -ln -s busybox "$root/bin/seq" -ln -s busybox "$root/bin/sh" -ln -s busybox "$root/bin/sleep" -ln -s busybox "$root/bin/stat" -ln -s busybox "$root/bin/test" -ln -s busybox "$root/bin/touch" -ln -s busybox "$root/bin/tr" -ln -s busybox "$root/bin/usleep" +ln -s busybox "$root/usr/bin/cat" +ln -s busybox "$root/usr/bin/hostname" +ln -s busybox "$root/usr/bin/ip" +ln -s busybox "$root/usr/bin/md5sum" +ln -s busybox "$root/usr/bin/mountpoint" +ln -s busybox "$root/usr/bin/ps" +ln -s busybox "$root/usr/bin/seq" +ln -s busybox "$root/usr/bin/sh" +ln -s busybox "$root/usr/bin/sleep" +ln -s busybox "$root/usr/bin/stat" +ln -s busybox "$root/usr/bin/test" +ln -s busybox "$root/usr/bin/touch" +ln -s busybox "$root/usr/bin/tr" +ln -s busybox "$root/usr/bin/true" +ln -s busybox "$root/usr/bin/usleep" -mkdir -p "$root/sbin" -cat <<'EOF' >"$root/sbin/init" +# Mock the bare minimum of getent to make systemd-nspawn --user= "work" +cat >"$root/usr/bin/getent" <<\EOF +#!/bin/sh + +if [[ $# - eq 0 ]]; then + : +elif [[ $1 == passwd ]]; then + echo "testuser:x:1000:1000:testuser:/:/bin/sh" +elif [[ $1 == initgroups ]]; then + echo "testuser" +fi +EOF +chmod +x "$root/usr/bin/getent" + +mkdir -p "$root/usr/sbin" +cat >"$root/usr/sbin/init" <<\EOF #!/bin/sh printf "ps aufx:\n" @@ -60,4 +78,8 @@ printf "%s\n\n" "$(cat /proc/1/gid_map)" printf "ip link:\n" ip link EOF -chmod +x "$root/sbin/init" +chmod +x "$root/usr/sbin/init" + +ln -srf "$root/usr/bin" "$root/bin" +ln -srf "$root/usr/sbin" "$root/sbin" +ln -srf "$root/usr/lib" "$root/lib" diff --git a/test/test-functions b/test/test-functions index 1f9fa6bb57..2a733d8b8f 100644 --- a/test/test-functions +++ b/test/test-functions @@ -775,7 +775,6 @@ setup_basic_environment() { install_testuser has_user_dbus_socket && install_user_dbus setup_selinux - instmods veth install_depmod_files generate_module_dependencies if get_bool "$IS_BUILT_WITH_ASAN"; then @@ -959,10 +958,10 @@ install_fs_tools() { install_modules() { dinfo "Install modules" - instmods loop - instmods vfat + instmods dummy vfat veth + instmods loop =block instmods nls_ascii =nls - instmods dummy + instmods overlay =overlayfs # for TEST-35-LOGIN instmods scsi_debug uinput @@ -1220,35 +1219,43 @@ install_systemd() { install_compiled_systemd fi - # remove unneeded documentation + # Remove unneeded documentation rm -fr "${initdir:?}"/usr/share/{man,doc} - # enable debug logging in PID1 - echo LogLevel=debug >>"$initdir/etc/systemd/system.conf" + # Enable debug logging in PID1 + mkdir -p "$initdir/etc/systemd/system.conf.d/" + echo -ne "[Manager]\nLogLevel=debug\n" >"$initdir/etc/systemd/system.conf.d/10-log-level.conf" if [[ -n "$TEST_SYSTEMD_LOG_LEVEL" ]]; then - echo DefaultEnvironment=SYSTEMD_LOG_LEVEL="$TEST_SYSTEMD_LOG_LEVEL" >>"$initdir/etc/systemd/system.conf" + echo DefaultEnvironment=SYSTEMD_LOG_LEVEL="$TEST_SYSTEMD_LOG_LEVEL" >>"$initdir/etc/systemd/system.conf.d/99-log-level.conf" fi - # store coredumps in journal - echo Storage=journal >>"$initdir/etc/systemd/coredump.conf" + # Store coredumps in journal + mkdir -p "$initdir/etc/systemd/coredump.conf.d/" + echo -ne "[Coredump]\nStorage=journal\n" >"$initdir/etc/systemd/coredump.conf.d/10-storage-journal.conf" # Propagate SYSTEMD_UNIT_PATH to user systemd managers - mkdir "$initdir/etc/systemd/system/user@.service.d/" - echo -e "[Service]\nPassEnvironment=SYSTEMD_UNIT_PATH\n" >"$initdir/etc/systemd/system/user@.service.d/override.conf" + mkdir -p "$initdir/etc/systemd/system/user@.service.d/" + echo -ne "[Service]\nPassEnvironment=SYSTEMD_UNIT_PATH\n" >"$initdir/etc/systemd/system/user@.service.d/99-SYSTEMD_UNIT_PATH.conf" # When built with gcov, disable ProtectSystem= and ProtectHome= in the test # images, since it prevents gcov to write the coverage reports (*.gcda # files) if get_bool "$IS_BUILT_WITH_COVERAGE"; then mkdir -p "$initdir/etc/systemd/system/service.d/" - echo -e "[Service]\nProtectSystem=no\nProtectHome=no\n" >"$initdir/etc/systemd/system/service.d/99-gcov-override.conf" + echo -ne "[Service]\nProtectSystem=no\nProtectHome=no\n" >"$initdir/etc/systemd/system/service.d/99-gcov-override.conf" # Similarly, set ReadWritePaths= to the $BUILD_DIR in the test image # to make the coverage work with units using DynamicUser=yes. Do this # only for services with test- prefix, as setting this system-wide # has many undesirable side-effects, as it creates its own namespace. mkdir -p "$initdir/etc/systemd/system/test-.service.d/" - echo -e "[Service]\nReadWritePaths=${BUILD_DIR:?}\n" >"$initdir/etc/systemd/system/test-.service.d/99-gcov-rwpaths-override.conf" + echo -ne "[Service]\nReadWritePaths=${BUILD_DIR:?}\n" >"$initdir/etc/systemd/system/test-.service.d/99-gcov-rwpaths-override.conf" # Ditto, but for the user daemon mkdir -p "$initdir/etc/systemd/user/test-.service.d/" - echo -e "[Service]\nReadWritePaths=${BUILD_DIR:?}\n" >"$initdir/etc/systemd/user/test-.service.d/99-gcov-rwpaths-override.conf" + echo -ne "[Service]\nReadWritePaths=${BUILD_DIR:?}\n" >"$initdir/etc/systemd/user/test-.service.d/99-gcov-rwpaths-override.conf" + # Bind the $BUILD_DIR into nspawn containers that are executed using + # machinectl. Unfortunately, the .nspawn files don't support drop-ins + # so we have to inject the bind mount directly into + # the systemd-nspawn@.service unit. + cp "$initdir/usr/lib/systemd/system/systemd-nspawn@.service" "$initdir/etc/systemd/system/systemd-nspawn@.service" + sed -ri "s/^ExecStart=.+$/& --bind=${BUILD_DIR//\//\\\/}/" "$initdir/etc/systemd/system/systemd-nspawn@.service" fi # If we're built with -Dportabled=false, tests with systemd-analyze diff --git a/test/units/testsuite-13.machinectl.sh b/test/units/testsuite-13.machinectl.sh index 50dc716230..8ccf4c5dc3 100755 --- a/test/units/testsuite-13.machinectl.sh +++ b/test/units/testsuite-13.machinectl.sh @@ -89,17 +89,17 @@ machinectl disable long-running long-running long-running container1 # Equivalent to machinectl kill --signal=SIGRTMIN+4 --kill-whom=leader rm -f /var/lib/machines/long-running/poweroff machinectl poweroff long-running -test -e /var/lib/machines/long-running/poweroff +timeout 10 sh -c "while ! test -e /var/lib/machines/long-running/poweroff; do sleep .5; done" machinectl poweroff long-running long-running long-running # Equivalent to machinectl kill --signal=SIGINT --kill-whom=leader rm -f /var/lib/machines/long-running/reboot machinectl reboot long-running -test -e /var/lib/machines/long-running/reboot +timeout 10 sh -c "while ! test -e /var/lib/machines/long-running/reboot; do sleep .5; done" machinectl reboot long-running long-running long-running # Skip machinectl terminate for now, as it doesn't play well with our "init" rm -f /var/lib/machines/long-running/trap machinectl kill --signal=SIGTRAP --kill-whom=leader long-running -test -e /var/lib/machines/long-running/trap +timeout 10 sh -c "while ! test -e /var/lib/machines/long-running/trap; do sleep .5; done" machinectl kill --signal=SIGTRAP --kill-whom=leader long-running long-running long-running # All used signals should've been caught by a handler [[ "$(machinectl show --property=State --value long-running)" == "running" ]] diff --git a/test/units/testsuite-13.nspawn.sh b/test/units/testsuite-13.nspawn.sh index c234887d05..22a06e8112 100755 --- a/test/units/testsuite-13.nspawn.sh +++ b/test/units/testsuite-13.nspawn.sh @@ -45,6 +45,223 @@ fi mkdir -p /var/lib/machines mount -t tmpfs tmpfs /var/lib/machines +testcase_sanity_check() { + local template root image oci uuid tmpdir + + template="$(mktemp -d /tmp/nspawn-template.XXX)" + "$CREATE_BB_CONTAINER" "$template" + # Create a simple image from the just created container template + image="$(mktemp /var/lib/machines/testsuite-13.image-XXX.img)" + dd if=/dev/zero of="$image" bs=1M count=32 + mkfs.ext4 "$image" + mkdir -p /mnt + mount -o loop "$image" /mnt + cp -r "$template"/* /mnt/ + umount /mnt + # Create a simple OCI bundle + oci="$(mktemp -d /var/lib/machines/testsuite-13.oci-bundle.XXX)" + "$CREATE_BB_CONTAINER" "$oci/rootfs" + cat >"$oci/config.json" </run/systemd/nspawn/foo-bar.nspawn + systemd-nspawn --directory="$root" \ + --machine=foo-bar \ + --settings=yes \ + sh -xec '[[ $container_uuid == deadbeef-dead-dead-beef-111111111111 ]]' + systemd-nspawn --directory="$root" \ + --machine=foo-bar \ + --uuid="$uuid" \ + --settings=yes \ + sh -xec "[[ \$container_uuid == $uuid ]]" + systemd-nspawn --directory="$root" \ + --machine=foo-bar \ + --uuid="$uuid" \ + --settings=override \ + sh -xec '[[ $container_uuid == deadbeef-dead-dead-beef-111111111111 ]]' + systemd-nspawn --directory="$root" \ + --machine=foo-bar \ + --uuid="$uuid" \ + --settings=trusted \ + sh -xec "[[ \$container_uuid == $uuid ]]" + + # Mounts + tmpdir="$(mktemp -d)" + mkdir "$tmpdir"/{1,2,3} + touch "$tmpdir/1/one" "$tmpdir/2/two" "$tmpdir/3/three" + touch "$tmpdir/foo" + # --bind= + systemd-nspawn --directory="$root" \ + --bind="$tmpdir:/foo" \ + sh -xec 'test -e /foo/foo; touch /foo/bar' + test -e "$tmpdir/bar" + # --bind-ro= + systemd-nspawn --directory="$root" \ + --bind-ro="$tmpdir:/foo" \ + sh -xec 'test -e /foo/foo; touch /foo/baz && exit 1; true' + # --inaccessible= + systemd-nspawn --directory="$root" \ + --inaccessible=/var \ + sh -xec 'touch /var/foo && exit 1; true' + # --tmpfs= + systemd-nspawn --directory="$root" \ + --tmpfs=/var:rw,nosuid,noexec \ + sh -xec 'touch /var/nope' + test ! -e "$root/var/nope" + # --overlay= + systemd-nspawn --directory="$root" \ + --overlay="$tmpdir/1:$tmpdir/2:$tmpdir/3:/var" \ + sh -xec 'test -e /var/one; test -e /var/two; test -e /var/three; touch /var/foo' + test -e "$tmpdir/3/foo" + # --overlay-ro= + systemd-nspawn --directory="$root" \ + --overlay-ro="$tmpdir/1:$tmpdir/2:$tmpdir/3:/var" \ + sh -xec 'test -e /var/one; test -e /var/two; test -e /var/three; touch /var/nope && exit 1; true' + test ! -e "$tmpdir/3/nope" + rm -fr "$tmpdir" + + # Assorted tests + systemd-nspawn --directory="$root" --suppress-sync=yes sh -xec 'echo hello' + systemd-nspawn --capability=help + systemd-nspawn --resolv-conf=help + systemd-nspawn --timezone=help + + # Handling of invalid arguments + opts=( + bind + bind-ro + bind-user + chdir + console + inaccessible + kill-signal + link-journal + load-credential + network-{interface,macvlan,ipvlan,veth-extra,bridge,zone} + no-new-privileges + oom-score-adjust + overlay + overlay-ro + personality + pivot-root + port + private-users + private-users-ownership + register + resolv-conf + rlimit + root-hash + root-hash-sig + set-credential + settings + suppress-sync + timezone + tmpfs + uuid + ) + for opt in "${opts[@]}"; do + (! systemd-nspawn "--$opt") + [[ "$opt" == network-zone ]] && continue + (! systemd-nspawn "--$opt=''") + (! systemd-nspawn "--$opt=%\$ลก") + done + (! systemd-nspawn --volatile="") + (! systemd-nspawn --volatile=-1) + (! systemd-nspawn --rlimit==) +} + testcase_check_bind_tmp_path() { # https://github.com/systemd/systemd/issues/4789 local root diff --git a/test/units/testsuite-13.service b/test/units/testsuite-13.service index a964d8d033..95c9a02fe1 100644 --- a/test/units/testsuite-13.service +++ b/test/units/testsuite-13.service @@ -1,6 +1,6 @@ # SPDX-License-Identifier: LGPL-2.1-or-later [Unit] -Description=TEST-13-NSPAWN-SMOKE +Description=TEST-13-NSPAWN [Service] ExecStartPre=rm -f /failed /testok