From 18fa5c8283528253a9a4d8af42ceac61cd23c42b Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Fri, 2 Jun 2023 20:28:41 +0200 Subject: [PATCH 01/12] test: move TPM2-related setup stuff into test-functions And hide it all behind $TEST_SETUP_SWTPM. --- test/TEST-70-TPM2/test.sh | 19 +------------ test/test-functions | 57 ++++++++++++++++++++++++++++++++------- 2 files changed, 49 insertions(+), 27 deletions(-) diff --git a/test/TEST-70-TPM2/test.sh b/test/TEST-70-TPM2/test.sh index f448a4a5f1..727d159094 100755 --- a/test/TEST-70-TPM2/test.sh +++ b/test/TEST-70-TPM2/test.sh @@ -5,6 +5,7 @@ set -e TEST_DESCRIPTION="cryptenroll/cryptsetup with TPM2 devices" IMAGE_NAME="tpm2" TEST_NO_NSPAWN=1 +TEST_SETUP_SWTPM=1 TEST_REQUIRE_INSTALL_TESTS=0 # shellcheck source=test/test-functions @@ -24,22 +25,4 @@ test_append_files() { inst_binary openssl } -TEST_70_TPM_DEVICE="tpm-tis" -if [[ "$(uname -m)" == "ppc64le" ]]; then - # tpm-spapr support was introduced in qemu 5.0.0. Skip test for old qemu versions. - qemu_min_version "5.0.0" || exit 0 - TEST_70_TPM_DEVICE="tpm-spapr" -fi - -TEST_70_at_exit() { - [[ -n "${TEST_70_SWTPM_PID:-}" ]] && kill "$TEST_70_SWTPM_PID" &>/dev/null - [[ -n "${TEST_70_TPM_STATE:-}" ]] && rm -rf "$TEST_70_TPM_STATE" -} - -TEST_70_TPM_STATE="$(mktemp -d)" -swtpm socket --tpm2 --tpmstate dir="$TEST_70_TPM_STATE" --ctrl type=unixio,path="$TEST_70_TPM_STATE/sock" & -TEST_70_SWTPM_PID=$! -add_at_exit_handler TEST_70_at_exit -QEMU_OPTIONS+=" -chardev socket,id=chrtpm,path=$TEST_70_TPM_STATE/sock -tpmdev emulator,id=tpm0,chardev=chrtpm -device $TEST_70_TPM_DEVICE,tpmdev=tpm0" - do_test "$@" diff --git a/test/test-functions b/test/test-functions index 2502177908..f374e8ade0 100644 --- a/test/test-functions +++ b/test/test-functions @@ -69,21 +69,14 @@ _at_exit() { # Run the EXIT handlers in reverse order for ((i = ${#_AT_EXIT_HANDLERS[@]} - 1; i >= 0; i--)); do ddebug "Running EXIT handler '${_AT_EXIT_HANDLERS[$i]}'" - "${_AT_EXIT_HANDLERS[$i]}" + eval "${_AT_EXIT_HANDLERS[$i]}" done } trap _at_exit EXIT add_at_exit_handler() { - local handler="${1?}" - - if [[ "$(type -t "$handler")" != "function" ]]; then - dfatal "'$handler' is not a function" - exit 1 - fi - - _AT_EXIT_HANDLERS+=("$handler") + _AT_EXIT_HANDLERS+=("${1:?}") } # Decide if we can (and want to) run qemu with KVM acceleration. @@ -364,6 +357,48 @@ find_qemu_bin() { fi } +qemu_setup_swtpm_socket() { + local pid state_dir tpm_device + + if ! tpm_device="$(qemu_get_tpm_device)"; then + dinfo "Found QEMU version is too old for TPM2 on ppc64le" + exit 0 + fi + + state_dir="$(mktemp -d)" + swtpm socket --tpm2 --tpmstate dir="$state_dir" --ctrl type=unixio,path="$state_dir/sock" & + pid=$! + if ! kill -0 "$pid"; then + echo >&2 "Failed to setup swtpm socket" + return 1 + fi + + dinfo "Started swtpm as PID $pid with state dir $state_dir" + + add_at_exit_handler "kill -TERM $pid 2>/dev/null; rm -rf '$state_dir'" + + QEMU_OPTIONS+=" -chardev socket,id=chrtpm,path=$state_dir/sock -tpmdev emulator,id=tpm0,chardev=chrtpm -device $tpm_device,tpmdev=tpm0" + dinfo "Configured emulated TPM2 device $tpm_device" + + return 0 +} + +qemu_get_tpm_device() { + local tpm_device="tpm-tis" + + if [[ "$(uname -m)" == "ppc64le" ]]; then + # tpm-spapr support was introduced in qemu 5.0.0 + if ! qemu_min_version "5.0.0"; then + return 1 + fi + + tpm_device="tpm-spapr" + fi + + echo "$tpm_device" + return 0 +} + # Compares argument #1=X.Y.Z (X&Y&Z = numeric) to the version of the installed qemu # returns 0 if newer or equal # returns 1 if older @@ -454,6 +489,10 @@ run_qemu() { find_qemu_bin || return 1 + if get_bool "${TEST_SETUP_SWTPM:-}"; then + qemu_setup_swtpm_socket || return 1 + fi + # Umount initdir to avoid concurrent access to the filesystem _umount_dir "$initdir" From 97d7af86b5fa718dcabe5073c0874cb1a8bcf927 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Fri, 2 Jun 2023 20:56:12 +0200 Subject: [PATCH 02/12] test: fix indentation --- test/TEST-70-TPM2/test.sh | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/TEST-70-TPM2/test.sh b/test/TEST-70-TPM2/test.sh index 727d159094..db92d21c4a 100755 --- a/test/TEST-70-TPM2/test.sh +++ b/test/TEST-70-TPM2/test.sh @@ -15,14 +15,14 @@ command -v swtpm >/dev/null 2>&1 || exit 0 command -v tpm2_pcrextend >/dev/null 2>&1 || exit 0 test_append_files() { - local workspace="${1:?}" + local workspace="${1:?}" - instmods tpm tpm_tis tpm_ibmvtpm - install_dmevent - generate_module_dependencies - inst_binary tpm2_pcrextend - inst_binary tpm2_pcrread - inst_binary openssl + instmods tpm tpm_tis tpm_ibmvtpm + install_dmevent + generate_module_dependencies + inst_binary tpm2_pcrextend + inst_binary tpm2_pcrread + inst_binary openssl } do_test "$@" From 70bdf6e661f67dfbfd6a198f7d1ebc6fdf0dce62 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Fri, 2 Jun 2023 21:10:08 +0200 Subject: [PATCH 03/12] test: introduce test_require_bin() and use it No functional change. --- test/TEST-21-DFUZZER/test.sh | 2 +- test/TEST-43-PRIVATEUSER-UNPRIV/test.sh | 2 +- test/TEST-46-HOMED/test.sh | 5 +---- test/TEST-50-DISSECT/test.sh | 4 +--- test/TEST-70-TPM2/test.sh | 3 +-- test/TEST-75-RESOLVED/test.sh | 5 +---- test/test-functions | 11 +++++++++++ 7 files changed, 17 insertions(+), 15 deletions(-) diff --git a/test/TEST-21-DFUZZER/test.sh b/test/TEST-21-DFUZZER/test.sh index eb0a6549e0..4b1919b86e 100755 --- a/test/TEST-21-DFUZZER/test.sh +++ b/test/TEST-21-DFUZZER/test.sh @@ -18,7 +18,7 @@ if ! get_bool "${TEST_PREFER_NSPAWN:=}"; then TEST_NO_NSPAWN=1 fi -command -v dfuzzer >/dev/null || exit 0 +test_require_bin dfuzzer if ! get_bool "$IS_BUILT_WITH_ASAN"; then echo "systemd is built without ASan, skipping..." diff --git a/test/TEST-43-PRIVATEUSER-UNPRIV/test.sh b/test/TEST-43-PRIVATEUSER-UNPRIV/test.sh index 844c08ab1f..1d1dab43c3 100755 --- a/test/TEST-43-PRIVATEUSER-UNPRIV/test.sh +++ b/test/TEST-43-PRIVATEUSER-UNPRIV/test.sh @@ -9,7 +9,7 @@ IMAGE_NAME="private-users" . "${TEST_BASE_DIR:?}/test-functions" has_user_dbus_socket || exit 0 -command -v mksquashfs >/dev/null 2>&1 || exit 0 +test_require_bin mksquashfs test_append_files() { inst_binary unsquashfs diff --git a/test/TEST-46-HOMED/test.sh b/test/TEST-46-HOMED/test.sh index 0daf211103..3bf3891380 100755 --- a/test/TEST-46-HOMED/test.sh +++ b/test/TEST-46-HOMED/test.sh @@ -11,10 +11,7 @@ TEST_DESCRIPTION="testing homed" . "${TEST_BASE_DIR:?}/test-functions" get_bool "${NO_BUILD:-}" && HOMECTL_BIN="homectl" || HOMECTL_BIN="${BUILD_DIR:?}/homectl" -if ! command -v "$HOMECTL_BIN" >/dev/null; then - echo "Built without systemd-homed, skipping the test" - exit 0 -fi +test_require_bin "$HOMECTL_BIN" # Need loop devices for mounting images test_append_files() { diff --git a/test/TEST-50-DISSECT/test.sh b/test/TEST-50-DISSECT/test.sh index 2d44ca2b6e..bcc81749af 100755 --- a/test/TEST-50-DISSECT/test.sh +++ b/test/TEST-50-DISSECT/test.sh @@ -12,9 +12,7 @@ TEST_INSTALL_VERITY_MINIMAL=1 # shellcheck source=test/test-functions . "${TEST_BASE_DIR:?}/test-functions" -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 +test_require_bin mksquashfs veritysetup sfdisk test_append_files() { instmods squashfs =squashfs diff --git a/test/TEST-70-TPM2/test.sh b/test/TEST-70-TPM2/test.sh index db92d21c4a..f3ac1399fc 100755 --- a/test/TEST-70-TPM2/test.sh +++ b/test/TEST-70-TPM2/test.sh @@ -11,8 +11,7 @@ TEST_REQUIRE_INSTALL_TESTS=0 # shellcheck source=test/test-functions . "${TEST_BASE_DIR:?}/test-functions" -command -v swtpm >/dev/null 2>&1 || exit 0 -command -v tpm2_pcrextend >/dev/null 2>&1 || exit 0 +test_require_bin swtpm tpm2_pcrextend test_append_files() { local workspace="${1:?}" diff --git a/test/TEST-75-RESOLVED/test.sh b/test/TEST-75-RESOLVED/test.sh index 6c63db65fb..cbb9e3dbbf 100755 --- a/test/TEST-75-RESOLVED/test.sh +++ b/test/TEST-75-RESOLVED/test.sh @@ -9,10 +9,7 @@ NSPAWN_ARGUMENTS="--private-network" # shellcheck source=test/test-functions . "${TEST_BASE_DIR:?}/test-functions" -if ! command -v knotd >/dev/null; then - echo "This test requires Knot DNS server, skipping..." - exit 0 -fi +test_require_bin knotd # We need at least Knot 3.0 which support (among others) the ds-push directive if ! knotc -c "${TEST_BASE_DIR:?}/knot-data/knot.conf" conf-check; then diff --git a/test/test-functions b/test/test-functions index f374e8ade0..09e5e0d38e 100644 --- a/test/test-functions +++ b/test/test-functions @@ -326,6 +326,17 @@ if get_bool "$IS_BUILT_WITH_ASAN"; then echo "Detected ASan RT '$ASAN_RT_NAME' located at '$ASAN_RT_PATH'" fi +test_require_bin() { + local bin + + for bin in "$@"; do + if ! command -v "$bin" >/dev/null; then + echo "Required binary $bin not available, skipping the test" + exit 0 + fi + done +} + find_qemu_bin() { QEMU_BIN="${QEMU_BIN:-""}" # SUSE and Red Hat call the binary qemu-kvm. Debian and Gentoo call it kvm. From 0334afe4d01b0f24d06995bb3ee4f5c2ff7d58c6 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Mon, 5 Jun 2023 09:39:51 +0200 Subject: [PATCH 04/12] test: make the root/data partition size configurable per test --- test/TEST-58-REPART/test.sh | 1 + test/test-functions | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/TEST-58-REPART/test.sh b/test/TEST-58-REPART/test.sh index 7549de568c..d6e6ac0b22 100755 --- a/test/TEST-58-REPART/test.sh +++ b/test/TEST-58-REPART/test.sh @@ -4,6 +4,7 @@ set -e TEST_DESCRIPTION="test systemd-repart" IMAGE_NAME="repart" +IMAGE_ADDITIONAL_ROOT_SIZE=1000 TEST_FORCE_NEWIMAGE=1 # shellcheck source=test/test-functions diff --git a/test/test-functions b/test/test-functions index 09e5e0d38e..5aa99522fc 100644 --- a/test/test-functions +++ b/test/test-functions @@ -1442,8 +1442,11 @@ create_empty_image() { fi fi - if [ "$IMAGE_NAME" = "repart" ]; then - root_size=$((root_size+=1000)) + if [[ "${IMAGE_ADDITIONAL_ROOT_SIZE:-0}" -gt 0 ]]; then + root_size=$((root_size + IMAGE_ADDITIONAL_ROOT_SIZE)) + fi + if [[ "${IMAGE_ADDITIONAL_DATA_SIZE:-0}" -gt 0 ]]; then + data_size=$((data_size + IMAGE_ADDITIONAL_DATA_SIZE)) fi echo "Setting up ${IMAGE_PUBLIC:?} (${root_size} MB)" From b7e913841b1136dc4f15415df27f95fe67923b08 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Mon, 5 Jun 2023 09:40:21 +0200 Subject: [PATCH 05/12] test: make the data partition larger for the cryptsetup test As we use it for /var and with the default 100 MiB there's not enough space for the journal. --- test/TEST-24-CRYPTSETUP/test.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/test/TEST-24-CRYPTSETUP/test.sh b/test/TEST-24-CRYPTSETUP/test.sh index 87ffaea453..c7e024ffed 100755 --- a/test/TEST-24-CRYPTSETUP/test.sh +++ b/test/TEST-24-CRYPTSETUP/test.sh @@ -4,6 +4,7 @@ set -e TEST_DESCRIPTION="cryptsetup systemd setup" IMAGE_NAME="cryptsetup" +IMAGE_ADDITIONAL_DATA_SIZE=100 TEST_NO_NSPAWN=1 TEST_FORCE_NEWIMAGE=1 From 00c2676972b62edff09ae612286e814bf9d4a574 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Sun, 4 Jun 2023 15:33:24 +0200 Subject: [PATCH 06/12] test: minor cleanup No functional change. --- test/test-functions | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/test-functions b/test/test-functions index 5aa99522fc..cfae5e9fda 100644 --- a/test/test-functions +++ b/test/test-functions @@ -1419,7 +1419,7 @@ cleanup_loopdev() { add_at_exit_handler cleanup_loopdev create_empty_image() { - if [ -z "${IMAGE_NAME:=}" ]; then + if [[ -z "${IMAGE_NAME:=}" ]]; then echo "create_empty_image: \$IMAGE_NAME not set" exit 1 fi @@ -1429,13 +1429,13 @@ create_empty_image() { local data_size=100 if ! get_bool "$NO_BUILD"; then if meson configure "${BUILD_DIR:?}" | grep 'static-lib\|standalone-binaries' | awk '{ print $2 }' | grep -q 'true'; then - root_size=$((root_size+=200)) + root_size=$((root_size + 200)) fi if meson configure "${BUILD_DIR:?}" | grep 'link-.*-shared' | awk '{ print $2 }' | grep -q 'false'; then - root_size=$((root_size+=200)) + root_size=$((root_size + 200)) fi if get_bool "$IS_BUILT_WITH_COVERAGE"; then - root_size=$((root_size+=250)) + root_size=$((root_size + 250)) fi if get_bool "$IS_BUILT_WITH_ASAN"; then root_size=$((root_size * 2)) @@ -1455,8 +1455,8 @@ create_empty_image() { # Create the blank file to use as a root filesystem truncate -s "${root_size}M" "$IMAGE_PUBLIC" - LOOPDEV=$(losetup --show -P -f "$IMAGE_PUBLIC") - [ -b "$LOOPDEV" ] || return 1 + LOOPDEV="$(losetup --show -P -f "$IMAGE_PUBLIC")" + [[ -b "$LOOPDEV" ]] || return 1 # Create two partitions - a root one and a data one (utilized by some tests) sfdisk "$LOOPDEV" < Date: Sun, 4 Jun 2023 15:45:08 +0200 Subject: [PATCH 07/12] test: clean up the test cleanup a bit --- test/TEST-24-CRYPTSETUP/test.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/TEST-24-CRYPTSETUP/test.sh b/test/TEST-24-CRYPTSETUP/test.sh index c7e024ffed..9bfbeac80c 100755 --- a/test/TEST-24-CRYPTSETUP/test.sh +++ b/test/TEST-24-CRYPTSETUP/test.sh @@ -62,6 +62,7 @@ test_create_image() { mkdir -p "$STATEDIR/keydev" mount "$STATEDIR/keydev.img" "$STATEDIR/keydev" echo -n test >"$STATEDIR/keydev/keyfile" + sync "$STATEDIR/keydev" umount "$STATEDIR/keydev" cat >>"$initdir/etc/fstab" < Date: Sun, 4 Jun 2023 16:02:45 +0200 Subject: [PATCH 08/12] cryptsetup: avoid calling strv_find() on a NULL pointer When the header= option comes before any other type= defining one, we trip over an assertion: Jun 04 15:45:33 H testsuite-24.sh[752]: + systemctl start systemd-cryptsetup@detached.service Jun 04 15:45:33 H systemd[1]: Starting systemd-cryptsetup@detached.service... Jun 04 15:45:33 H systemd-cryptsetup[4641]: Assertion 'name' failed at src/basic/strv.c:21, function strv_find(). Aborting. ... Jun 04 15:45:33 H systemd-coredump[4643]: Process 4641 (systemd-cryptse) of user 0 dumped core. ... Stack trace of thread 4641: #0 0x00007ff9256afe5c __pthread_kill_implementation (libc.so.6 + 0x8ce5c) #1 0x00007ff92565fa76 raise (libc.so.6 + 0x3ca76) #2 0x00007ff9256497fc abort (libc.so.6 + 0x267fc) #3 0x00007ff926076047 log_assert_failed (libsystemd-shared-253.so + 0x276047) #4 0x00007ff9260ab317 strv_find (libsystemd-shared-253.so + 0x2ab317) #5 0x0000000000405927 parse_one_option (systemd-cryptsetup + 0x5927) #6 0x0000000000407793 parse_options (systemd-cryptsetup + 0x7793) #7 0x000000000040fa0c run (systemd-cryptsetup + 0xfa0c) #8 0x000000000041137f main (systemd-cryptsetup + 0x1137f) #9 0x00007ff92564a510 __libc_start_call_main (libc.so.6 + 0x27510) #10 0x00007ff92564a5c9 __libc_start_main@@GLIBC_2.34 (libc.so.6 + 0x275c9) #11 0x0000000000403915 _start (systemd-cryptsetup + 0x3915) ELF object binary architecture: AMD x86-64 --- src/cryptsetup/cryptsetup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index d58defcc42..49b72131d8 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -234,7 +234,7 @@ static int parse_one_option(const char *option) { return log_oom(); } else if ((val = startswith(option, "header="))) { - if (!STR_IN_SET(arg_type, ANY_LUKS, CRYPT_LUKS1, CRYPT_LUKS2, CRYPT_TCRYPT)) + if (!arg_type || !STR_IN_SET(arg_type, ANY_LUKS, CRYPT_LUKS1, CRYPT_LUKS2, CRYPT_TCRYPT)) arg_type = ANY_LUKS; if (!path_is_absolute(val)) From e6faf0ee22cb7a449f1462f5a032110b46be31d5 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Sun, 4 Jun 2023 22:13:58 +0200 Subject: [PATCH 09/12] test: use check_result_common() The TEST-24 has been silently timing out for quite a while in the C8S job, as the check_result_qemu() override lacked some error checks, whoopsie. --- test/TEST-24-CRYPTSETUP/test.sh | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/test/TEST-24-CRYPTSETUP/test.sh b/test/TEST-24-CRYPTSETUP/test.sh index 9bfbeac80c..8ed5cf0e1b 100755 --- a/test/TEST-24-CRYPTSETUP/test.sh +++ b/test/TEST-24-CRYPTSETUP/test.sh @@ -17,24 +17,19 @@ KERNEL_APPEND+=" rd.luks=1 luks.name=$PART_UUID=$DM_NAME luks.key=$PART_UUID=/ke QEMU_OPTIONS+=" -drive format=raw,cache=unsafe,file=${STATEDIR:?}/keydev.img" check_result_qemu() { - local ret=1 + local ret mount_initdir - [[ -e "${initdir:?}/testok" ]] && ret=0 - [[ -f "$initdir/failed" ]] && cp -a "$initdir/failed" "${TESTDIR:?}" cryptsetup luksOpen "${LOOPDEV:?}p2" "${DM_NAME:?}" <"$TESTDIR/keyfile" mount "/dev/mapper/$DM_NAME" "$initdir/var" - save_journal "$initdir/var/log/journal" - check_coverage_reports "${initdir:?}" || ret=5 + + check_result_common "${initdir:?}" && ret=0 || ret=$? + _umount_dir "$initdir/var" _umount_dir "$initdir" cryptsetup luksClose "/dev/mapper/$DM_NAME" - [[ -f "$TESTDIR/failed" ]] && cat "$TESTDIR/failed" - echo "${JOURNAL_LIST:-No journals were saved}" - - test -s "$TESTDIR/failed" && ret=1 return $ret } From 71d7f02cc7dc1bf5b8506c90571cb980ec706def Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Sun, 4 Jun 2023 22:16:58 +0200 Subject: [PATCH 10/12] test: make check_result_*() `set -e` friendly --- test/test-functions | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/test-functions b/test/test-functions index cfae5e9fda..b17a74a450 100644 --- a/test/test-functions +++ b/test/test-functions @@ -1711,8 +1711,7 @@ check_result_nspawn() { fi fi - check_result_common "${workspace}" - ret=$? + check_result_common "${workspace}" && ret=0 || ret=$? _umount_dir "${initdir:?}" @@ -1732,8 +1731,7 @@ check_result_qemu() { fi fi - check_result_common "${initdir:?}" - ret=$? + check_result_common "${initdir:?}" && ret=0 || ret=$? _umount_dir "${initdir:?}" From eb26f34a0951f994fe3c1e6d1bc97db12db26844 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Sun, 4 Jun 2023 14:44:42 +0200 Subject: [PATCH 11/12] test: add a couple more tests for systemd-cryptsetup --- test/units/testsuite-24.service | 2 +- test/units/testsuite-24.sh | 216 ++++++++++++++++++++++++++++++++ 2 files changed, 217 insertions(+), 1 deletion(-) create mode 100755 test/units/testsuite-24.sh diff --git a/test/units/testsuite-24.service b/test/units/testsuite-24.service index ccae834371..e192d1ccad 100644 --- a/test/units/testsuite-24.service +++ b/test/units/testsuite-24.service @@ -5,5 +5,5 @@ After=multi-user.target [Service] ExecStartPre=rm -f /failed /testok -ExecStart=sh -x -e -c 'mountpoint /var; systemctl --state=failed --no-legend --no-pager >/failed; echo OK >/testok' +ExecStart=/usr/lib/systemd/tests/testdata/units/%N.sh Type=oneshot diff --git a/test/units/testsuite-24.sh b/test/units/testsuite-24.sh new file mode 100755 index 0000000000..391dcf999d --- /dev/null +++ b/test/units/testsuite-24.sh @@ -0,0 +1,216 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: LGPL-2.1-or-later +set -eux +set -o pipefail + +# TODO: +# - /proc/cmdline parsing +# - figure out token support (apart from TPM2, as that's covered by TEST-70-TPM2) +# - this might help https://www.qemu.org/docs/master/system/devices/ccid.html +# - expect + interactive auth? + +# We set up an encrypted /var partition which should get mounted automatically +# on boot +mountpoint /var + +systemctl --state=failed --no-legend --no-pager | tee /failed +if [[ -s /failed ]]; then + echo >&2 "Found units in failed state" + exit 1 +fi + +at_exit() { + set +e + + mountpoint -q /proc/cmdline && umount /proc/cmdline + rm -f /etc/crypttab + [[ -e /tmp/crypttab.bak ]] && cp -fv /tmp/crypttab.bak /etc/crypttab + [[ -n "${STORE_LOOP:-}" ]] && losetup -d "$STORE_LOOP" + [[ -n "${WORKDIR:-}" ]] && rm -rf "$WORKDIR" + + systemctl daemon-reload +} + +trap at_exit EXIT + +cryptsetup_start_and_check() { + local expect_fail=0 + local ec volume unit + + if [[ "${1:?}" == "-f" ]]; then + expect_fail=1 + shift + fi + + for volume in "$@"; do + unit="systemd-cryptsetup@$volume.service" + + # The unit existence check should always pass + [[ "$(systemctl show -P LoadState "$unit")" == loaded ]] + systemctl list-unit-files "$unit" + + systemctl start "$unit" && ec=0 || ec=$? + if [[ "$expect_fail" -ne 0 ]]; then + if [[ "$ec" -eq 0 ]]; then + echo >&2 "Unexpected pass when starting $unit" + return 1 + fi + + return 0 + fi + + if [[ "$ec" -ne 0 ]]; then + echo >&2 "Unexpected fail when starting $unit" + return 1 + fi + + systemctl status "$unit" + test -e "/dev/mapper/$volume" + systemctl stop "$unit" + test ! -e "/dev/mapper/$volume" + done + + return 0 +} + +# Note: some stuff (especially TPM-related) is already tested by TEST-70-TPM2, +# so focus more on other areas instead + +# Use a common workdir to make the cleanup easier +WORKDIR="$(mktemp -d)" + +# Prepare a couple of LUKS2-encrypted disk images +# +# 1) Image with an empty password +IMAGE_EMPTY="$WORKDIR/empty.img)" +IMAGE_EMPTY_KEYFILE="$WORKDIR/empty.keyfile" +IMAGE_EMPTY_KEYFILE_ERASE="$WORKDIR/empty-erase.keyfile" +IMAGE_EMPTY_KEYFILE_ERASE_FAIL="$WORKDIR/empty-erase-fail.keyfile)" +truncate -s 32M "$IMAGE_EMPTY" +echo -n passphrase >"$IMAGE_EMPTY_KEYFILE" +chmod 0600 "$IMAGE_EMPTY_KEYFILE" +cryptsetup luksFormat --batch-mode \ + --pbkdf pbkdf2 \ + --pbkdf-force-iterations 1000 \ + --use-urandom \ + "$IMAGE_EMPTY" "$IMAGE_EMPTY_KEYFILE" +PASSWORD=passphrase NEWPASSWORD="" systemd-cryptenroll --password "$IMAGE_EMPTY" +# Duplicate the key file to test keyfile-erase as well +cp -v "$IMAGE_EMPTY_KEYFILE" "$IMAGE_EMPTY_KEYFILE_ERASE" +# The key should get erased even on a failed attempt, so test that too +cp -v "$IMAGE_EMPTY_KEYFILE" "$IMAGE_EMPTY_KEYFILE_ERASE_FAIL" + +# 2) Image with a detached header and a key file offset + size +IMAGE_DETACHED="$WORKDIR/detached.img" +IMAGE_DETACHED_KEYFILE="$WORKDIR/detached.keyfile" +IMAGE_DETACHED_KEYFILE2="$WORKDIR/detached.keyfile2" +IMAGE_DETACHED_HEADER="$WORKDIR/detached.header" +truncate -s 32M "$IMAGE_DETACHED" +dd if=/dev/urandom of="$IMAGE_DETACHED_KEYFILE" count=64 bs=1 +dd if=/dev/urandom of="$IMAGE_DETACHED_KEYFILE2" count=32 bs=1 +chmod 0600 "$IMAGE_DETACHED_KEYFILE" "$IMAGE_DETACHED_KEYFILE2" +cryptsetup luksFormat --batch-mode \ + --pbkdf pbkdf2 \ + --pbkdf-force-iterations 1000 \ + --use-urandom \ + --header "$IMAGE_DETACHED_HEADER" \ + --keyfile-offset 32 \ + --keyfile-size 16 \ + "$IMAGE_DETACHED" "$IMAGE_DETACHED_KEYFILE" +# Also, add a second key file to key slot 8 +# Note: --key-slot= behaves as --new-key-slot= when used alone for backwards compatibility +cryptsetup luksAddKey --batch-mode \ + --header "$IMAGE_DETACHED_HEADER" \ + --key-file "$IMAGE_DETACHED_KEYFILE" \ + --keyfile-offset 32 \ + --keyfile-size 16 \ + --key-slot 8 \ + "$IMAGE_DETACHED" "$IMAGE_DETACHED_KEYFILE2" + +# Prepare a couple of dummy devices we'll store a copy of the detached header +# and one of the keys on to test if systemd-cryptsetup correctly mounts them +# when necessary +STORE_IMAGE="$WORKDIR/store.img" +truncate -s 64M "$STORE_IMAGE" +STORE_LOOP="$(losetup --show --find --partscan "$STORE_IMAGE")" +sfdisk "$STORE_LOOP" </etc/crypttab </tmp/cmdline.tmp +mount --bind /tmp/cmdline.tmp /proc/cmdline +# Run the systemd-cryptsetup-generator once explicitly, to collect coverage, +# as during daemon-reload we run generators in a sandbox +mkdir -p /tmp/systemd-cryptsetup-generator.out +/usr/lib/systemd/system-generators/systemd-cryptsetup-generator /tmp/systemd-cryptsetup-generator.out/ +systemctl daemon-reload +systemctl list-unit-files "systemd-cryptsetup@*" + +cryptsetup_start_and_check empty_key +test -e "$IMAGE_EMPTY_KEYFILE_ERASE" +cryptsetup_start_and_check empty_key_erase +test ! -e "$IMAGE_EMPTY_KEYFILE_ERASE" +test -e "$IMAGE_EMPTY_KEYFILE_ERASE_FAIL" +cryptsetup_start_and_check -f empty_key_erase_fail +test ! -e "$IMAGE_EMPTY_KEYFILE_ERASE_FAIL" +cryptsetup_start_and_check -f empty_fail{0..1} +cryptsetup_start_and_check empty{0..1} +# First, check if we correctly fail without any key +cryptsetup_start_and_check -f empty_nokey +# And now provide the key via /{etc,run}/cryptsetup-keys.d/ +mkdir -p /run/cryptsetup-keys.d +cp "$IMAGE_EMPTY_KEYFILE" /run/cryptsetup-keys.d/empty_nokey.key +cryptsetup_start_and_check empty_nokey + +cryptsetup_start_and_check detached +cryptsetup_start_and_check detached_store{0..2} +cryptsetup_start_and_check -f detached_fail{0..4} +cryptsetup_start_and_check detached_slot{0..1} +cryptsetup_start_and_check -f detached_slot_fail + +echo OK >/testok From d7c1df84d9e9da81889e44836b054a1af94620e5 Mon Sep 17 00:00:00 2001 From: Frantisek Sumsal Date: Mon, 5 Jun 2023 16:54:31 +0200 Subject: [PATCH 12/12] test: make sure we unmount /var late during shutdown To avoid the "mountpoint is busy" error. --- test/TEST-24-CRYPTSETUP/test.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/TEST-24-CRYPTSETUP/test.sh b/test/TEST-24-CRYPTSETUP/test.sh index 8ed5cf0e1b..d0ec63d870 100755 --- a/test/TEST-24-CRYPTSETUP/test.sh +++ b/test/TEST-24-CRYPTSETUP/test.sh @@ -13,7 +13,13 @@ TEST_FORCE_NEWIMAGE=1 PART_UUID="deadbeef-dead-dead-beef-000000000000" DM_NAME="test24_varcrypt" -KERNEL_APPEND+=" rd.luks=1 luks.name=$PART_UUID=$DM_NAME luks.key=$PART_UUID=/keyfile:LABEL=varcrypt_keydev" +KERNEL_OPTIONS=( + "rd.luks=1" + "luks.name=$PART_UUID=$DM_NAME" + "luks.key=$PART_UUID=/keyfile:LABEL=varcrypt_keydev" + "luks.options=$PART_UUID=x-initrd.attach" +) +KERNEL_APPEND+=" ${KERNEL_OPTIONS[*]}" QEMU_OPTIONS+=" -drive format=raw,cache=unsafe,file=${STATEDIR:?}/keydev.img" check_result_qemu() {