From: Lennart Poettering Date: Mon, 17 Mar 2025 20:38:12 +0000 (+0100) Subject: gpt-auto-generator: add support for setting up verity partitions automatically X-Git-Tag: v258-rc1~923^2~11 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=0a64b7ba6e4e77b0e70d3022078032d1e63599a5;p=thirdparty%2Fsystemd.git gpt-auto-generator: add support for setting up verity partitions automatically So far the gpt-auto-generator would only cover unprotected and encrypted partitions. Teach it handling of verity too. --- diff --git a/src/gpt-auto-generator/gpt-auto-generator.c b/src/gpt-auto-generator/gpt-auto-generator.c index c7acbcb2b0c..b9b5b60da88 100644 --- a/src/gpt-auto-generator/gpt-auto-generator.c +++ b/src/gpt-auto-generator/gpt-auto-generator.c @@ -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; diff --git a/src/shared/generator.c b/src/shared/generator.c index 90568e3ec94..5e3cf2a6cb6 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -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;