diff --git a/man/crypttab.xml b/man/crypttab.xml index e94bf1ca17..eb742be058 100644 --- a/man/crypttab.xml +++ b/man/crypttab.xml @@ -322,7 +322,9 @@ unsuccessful. Note that other units that depend on the unlocked device may still fail. In particular, if the device is used for a mount point, the mount point itself also needs to have the option, or the boot will fail if the device is not unlocked - successfully. + successfully. If a keyfile and/or a are specified, the dependencies on + their respective directories will also not be fatal, so that umounting said directories will + not cause the generated cryptset unit to be deactivated. diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 904e4cd3fa..93bbd833fe 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -229,7 +229,8 @@ static int generate_device_umount(const char *name, static int print_dependencies(FILE *f, const char* device_path, const char* timeout_value, bool canfail) { int r; - assert(!canfail || timeout_value); + assert(f); + assert(device_path); if (STR_IN_SET(device_path, "-", "none")) /* None, nothing to do */ @@ -263,11 +264,13 @@ static int print_dependencies(FILE *f, const char* device_path, const char* time fprintf(f, "After=%1$s\n", unit); if (canfail) { fprintf(f, "Wants=%1$s\n", unit); - r = write_drop_in_format(arg_dest, unit, 90, "device-timeout", - "# Automatically generated by systemd-cryptsetup-generator \n\n" - "[Unit]\nJobRunningTimeoutSec=%s", timeout_value); - if (r < 0) - return log_error_errno(r, "Failed to write device drop-in: %m"); + if (timeout_value) { + r = write_drop_in_format(arg_dest, unit, 90, "device-timeout", + "# Automatically generated by systemd-cryptsetup-generator \n\n" + "[Unit]\nJobRunningTimeoutSec=%s", timeout_value); + if (r < 0) + return log_error_errno(r, "Failed to write device drop-in: %m"); + } } else fprintf(f, "Requires=%1$s\n", unit); } else { @@ -276,7 +279,7 @@ static int print_dependencies(FILE *f, const char* device_path, const char* time if (!escaped_path) return log_oom(); - fprintf(f, "RequiresMountsFor=%s\n", escaped_path); + fprintf(f, "%s=%s\n", canfail ? "WantsMountsFor" : "RequiresMountsFor", escaped_path); } return 0; @@ -486,7 +489,7 @@ static int create_disk( if (key_file && !keydev) { r = print_dependencies(f, key_file, keyfile_timeout_value, - /* canfail= */ keyfile_can_timeout > 0); + /* canfail= */ keyfile_can_timeout > 0 || nofail); if (r < 0) return r; } @@ -494,8 +497,8 @@ static int create_disk( /* Check if a header option was specified */ if (detached_header > 0 && !headerdev) { r = print_dependencies(f, header_path, - NULL, - /* canfail= */ false); /* header is always necessary */ + /* timeout_value= */ NULL, + /* canfail= */ nofail); if (r < 0) return r; } diff --git a/test/units/testsuite-24.sh b/test/units/testsuite-24.sh index c815f908d1..0a8a920eeb 100755 --- a/test/units/testsuite-24.sh +++ b/test/units/testsuite-24.sh @@ -35,6 +35,7 @@ trap at_exit EXIT cryptsetup_start_and_check() { local expect_fail=0 + local umount_header_and_key=0 local ec volume unit if [[ "${1:?}" == "-f" ]]; then @@ -42,6 +43,11 @@ cryptsetup_start_and_check() { shift fi + if [[ "${1:?}" == "-u" ]]; then + umount_header_and_key=1 + shift + fi + for volume in "$@"; do unit="systemd-cryptsetup@$volume.service" @@ -64,6 +70,12 @@ cryptsetup_start_and_check() { return 1 fi + if [[ "$umount_header_and_key" -ne 0 ]]; then + umount "$TMPFS_DETACHED_KEYFILE" + umount "$TMPFS_DETACHED_HEADER" + udevadm settle --timeout=30 + fi + systemctl status "$unit" test -e "/dev/mapper/$volume" systemctl stop "$unit" @@ -148,6 +160,15 @@ mkfs.ext4 -L keyfile_store "/dev/disk/by-partlabel/keyfile_store" mount "/dev/disk/by-partlabel/keyfile_store" /mnt cp "$IMAGE_DETACHED_KEYFILE2" /mnt/keyfile umount /mnt + +# Also copy the key and header on a tmpfs that we will umount after unlocking +TMPFS_DETACHED_KEYFILE="$(mktemp -d)" +TMPFS_DETACHED_HEADER="$(mktemp -d)" +mount -t tmpfs -o size=32M tmpfs "$TMPFS_DETACHED_KEYFILE" +mount -t tmpfs -o size=32M tmpfs "$TMPFS_DETACHED_HEADER" +cp "$IMAGE_DETACHED_KEYFILE" "$TMPFS_DETACHED_KEYFILE/keyfile" +cp "$IMAGE_DETACHED_HEADER" "$TMPFS_DETACHED_HEADER/header" + udevadm settle --timeout=30 # Prepare our test crypttab @@ -177,6 +198,7 @@ detached_fail4 $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE headless=1, detached_slot0 $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE2 headless=1,header=$IMAGE_DETACHED_HEADER detached_slot1 $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE2 headless=1,header=$IMAGE_DETACHED_HEADER,key-slot=8 detached_slot_fail $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE2 headless=1,header=$IMAGE_DETACHED_HEADER,key-slot=0 +detached_nofail $IMAGE_DETACHED $TMPFS_DETACHED_KEYFILE/keyfile headless=1,header=$TMPFS_DETACHED_HEADER/header,keyfile-offset=32,keyfile-size=16,nofail EOF # Temporarily drop luks.name=/luks.uuid= from the kernel command line, as it makes @@ -212,5 +234,6 @@ 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 +cryptsetup_start_and_check -u detached_nofail touch /testok