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