]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
gpt-auto-generator: add support for setting up verity partitions automatically
authorLennart Poettering <lennart@poettering.net>
Mon, 17 Mar 2025 20:38:12 +0000 (21:38 +0100)
committerLennart Poettering <lennart@poettering.net>
Thu, 3 Apr 2025 09:08:57 +0000 (11:08 +0200)
So far the gpt-auto-generator would only cover unprotected and encrypted
partitions. Teach it handling of verity too.

src/gpt-auto-generator/gpt-auto-generator.c
src/shared/generator.c

index c7acbcb2b0c372089198acbf578ebe07d27343f3..b9b5b60da88ee3a68367ec0940138328ac51d374 100644 (file)
@@ -24,6 +24,7 @@
 #include "fstab-util.h"
 #include "generator.h"
 #include "gpt.h"
+#include "hexdecoct.h"
 #include "image-policy.h"
 #include "initrd-util.h"
 #include "mountpoint-util.h"
@@ -184,6 +185,106 @@ static int add_cryptsetup(
 #endif
 }
 
+#if ENABLE_EFI
+static int add_veritysetup(
+                const char *id,
+                const char *data_what,
+                const char *hash_what,
+                const char *mount_opts) {
+
+#if HAVE_LIBCRYPTSETUP
+        int r;
+
+        assert(id);
+        assert(data_what);
+        assert(hash_what);
+
+        _cleanup_free_ char *dd = NULL;
+        r = unit_name_from_path(data_what, ".device", &dd);
+        if (r < 0)
+                return log_error_errno(r, "Failed to generate data device unit name: %m");
+
+        _cleanup_free_ char *dh = NULL;
+        r = unit_name_from_path(hash_what, ".device", &dh);
+        if (r < 0)
+                return log_error_errno(r, "Failed to generate hash device unit name: %m");
+
+        _cleanup_free_ char *e = unit_name_escape(id);
+        if (!e)
+                return log_oom();
+
+        _cleanup_free_ char *n = NULL;
+        r = unit_name_build("systemd-veritysetup", e, ".service", &n);
+        if (r < 0)
+                return log_error_errno(r, "Failed to generate unit name: %m");
+
+        _cleanup_fclose_ FILE *f = NULL;
+        r = generator_open_unit_file(arg_dest, /* source= */ NULL, n, &f);
+        if (r < 0)
+                return r;
+
+        r = generator_write_veritysetup_unit_section(f, /* source= */ NULL);
+        if (r < 0)
+                return r;
+
+        fprintf(f,
+                "Before=veritysetup.target\n"
+                "BindsTo=%1$s %2$s\n"
+                "After=%1$s %2$s\n",
+                dd, dh);
+
+        r = generator_write_veritysetup_service_section(
+                        f,
+                        id,
+                        data_what,
+                        hash_what,
+                        /* roothash= */ NULL,        /* NULL means: derive root hash from udev property ID_DISSECT_PART_ROOTHASH */
+                        "root-hash-signature=auto"); /* auto means: derive signature from udev property ID_DISSECT_PART_ROOTHASH_SIG */
+        if (r < 0)
+                return r;
+
+        r = fflush_and_check(f);
+        if (r < 0)
+                return log_error_errno(r, "Failed to write file %s: %m", n);
+
+        r = generator_write_device_timeout(arg_dest, data_what, mount_opts, /* filtered= */ NULL);
+        if (r < 0)
+                return r;
+
+        r = generator_write_device_timeout(arg_dest, hash_what, mount_opts, /* filtered= */ NULL);
+        if (r < 0)
+                return r;
+
+        r = generator_add_symlink(arg_dest, dd, "wants", n);
+        if (r < 0)
+                return r;
+
+        r = generator_add_symlink(arg_dest, dh, "wants", n);
+        if (r < 0)
+                return r;
+
+        _cleanup_free_ char *dmname = NULL;
+        dmname = strjoin("dev-mapper-", e, ".device");
+        if (!dmname)
+                return log_oom();
+
+        r = write_drop_in_format(
+                        arg_dest,
+                        dmname, 50, "job-timeout",
+                        "# Automatically generated by systemd-gpt-auto-generator\n\n"
+                        "[Unit]\n"
+                        "JobTimeoutSec=infinity"); /* the binary handles timeouts anyway */
+        if (r < 0)
+                return log_error_errno(r, "Failed to write device timeout drop-in: %m");
+
+        return 0;
+#else
+        return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
+                               "Partition is Verity protected, but systemd-gpt-auto-generator was compiled without libcryptsetup support.");
+#endif
+}
+#endif
+
 static int add_mount(
                 const char *id,
                 const char *what,
@@ -757,6 +858,18 @@ static int add_root_mount(void) {
                 r = add_root_cryptsetup();
                 if (r < 0)
                         return r;
+
+                /* If a device /dev/disk/by-designator/root-verity or
+                 * /dev/disk/by-designator/root-verity-data appears, then make it pull in
+                 * systemd-cryptsetup@root.service, which sets it up, and causes /dev/disk/by-designator/root
+                 * to appear. */
+                r = add_veritysetup(
+                                "root",
+                                "/dev/disk/by-designator/root-verity-data",
+                                "/dev/disk/by-designator/root-verity",
+                                arg_root_options);
+                if (r < 0)
+                        return r;
         }
 
         /* Note that we do not need to enable systemd-remount-fs.service here. If /etc/fstab exists,
@@ -793,7 +906,6 @@ static int add_root_mount(void) {
 #endif
 }
 
-
 static int add_usr_mount(void) {
 #if ENABLE_EFI
         int r;
@@ -828,6 +940,18 @@ static int add_usr_mount(void) {
                                 /* ret_device= */ NULL);
                 if (r < 0)
                         return r;
+
+                /* If a device /dev/disk/by-designator/usr-verity or
+                 * /dev/disk/by-designator/usr-verity-data appears, then make it pull in
+                 * systemd-cryptsetup@usr.service, which sets it up, and causes /dev/disk/by-designator/usr
+                 * to appear. */
+                r = add_veritysetup(
+                                "usr",
+                                "/dev/disk/by-designator/usr-verity-data",
+                                "/dev/disk/by-designator/usr-verity",
+                                arg_usr_options);
+                if (r < 0)
+                        return r;
         }
 
         _cleanup_free_ char *options = NULL;
index 90568e3ec94d416cf3790591e3fa1b70b747d8e0..5e3cf2a6cb6c79004bdc95fbecbd0a739c247d45 100644 (file)
@@ -1026,9 +1026,11 @@ int generator_write_veritysetup_service_section(
         if (!hash_what_escaped)
                 return log_oom();
 
-        roothash_escaped = specifier_escape(roothash);
-        if (!roothash_escaped)
-                return log_oom();
+        if (roothash) {
+                roothash_escaped = specifier_escape(roothash);
+                if (!roothash_escaped)
+                        return log_oom();
+        }
 
         if (options) {
                 options_escaped = specifier_escape(options);
@@ -1043,7 +1045,7 @@ int generator_write_veritysetup_service_section(
                 "RemainAfterExit=yes\n"
                 "ExecStart=" SYSTEMD_VERITYSETUP_PATH " attach '%s' '%s' '%s' '%s' '%s'\n"
                 "ExecStop=" SYSTEMD_VERITYSETUP_PATH " detach '%s'\n",
-                name_escaped, data_what_escaped, hash_what_escaped, roothash_escaped, strempty(options_escaped),
+                name_escaped, data_what_escaped, hash_what_escaped, empty_to_dash(roothash_escaped), strempty(options_escaped),
                 name_escaped);
 
         return 0;