]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
cryptsetup: use WantsMountsFor= for key/header when nofail is set
authorLuca Boccassi <bluca@debian.org>
Mon, 27 Nov 2023 14:03:36 +0000 (14:03 +0000)
committerLuca Boccassi <bluca@debian.org>
Wed, 29 Nov 2023 11:04:59 +0000 (11:04 +0000)
The header and keyfile are necessary only for opening the device, not
for closing, so it is not necessary to deactivate the generated
cryptsetup unit when the header or keyfile backing store are removed.

This is especially useful in the case of softreboot, when the new
mount root is setup under /run/nextroot/ but we don't want to close
the cryptsetup devices for encrypted /var/ or so, and we simply
mount it directly on /run/nextroot/var/ before the soft-reboot.

man/crypttab.xml
src/cryptsetup/cryptsetup-generator.c
test/units/testsuite-24.sh

index e94bf1ca17828f0629f2431d930ae0d36c99f771..eb742be058221f5e438f047208ace545ea1d6904 100644 (file)
         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>nofail</option> option, or the boot will fail if the device is not unlocked
-        successfully.</para>
+        successfully. If a keyfile and/or a <option>header</option> 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.</para>
 
         <xi:include href="version-info.xml" xpointer="v186"/></listitem>
       </varlistentry>
index 904e4cd3fafaf9730e26f443954476e1f7cb2e9e..93bbd833fe303c64c07337c5b2b7644d202dd98a 100644 (file)
@@ -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;
         }
index c815f908d11417ea850f3dc575bfec6a4f60cb4e..0a8a920eeb430f099aab5498c0a5c563cb33ce42 100755 (executable)
@@ -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