diff options
author | Luca Boccassi <luca.boccassi@microsoft.com> | 2021-11-22 14:09:38 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-11-22 14:09:38 +0100 |
commit | d837adb0a8bf38902b2fcbe7149a22e4ebd3f318 (patch) | |
tree | abb35298f0699c20c320f89f7fbbf36f2eb3f54b /src | |
parent | FIDO2 device removal instructions (#21426) (diff) | |
parent | Document usr-specific verity parameters (diff) | |
download | systemd-d837adb0a8bf38902b2fcbe7149a22e4ebd3f318.tar.xz systemd-d837adb0a8bf38902b2fcbe7149a22e4ebd3f318.zip |
Merge pull request #21357 from mbd98/usr-verity-auto
veritysetup-generator, fstab-generator: Setup and mount usr verity device when 'usrhash' (and optionally systemd.verity_usr_*) is present as kernel command line parameter
Diffstat (limited to 'src')
-rw-r--r-- | src/fstab-generator/fstab-generator.c | 35 | ||||
-rw-r--r-- | src/veritysetup/veritysetup-generator.c | 193 |
2 files changed, 167 insertions, 61 deletions
diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 1e6ad432dc..b764bee215 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -50,6 +50,7 @@ static int arg_root_rw = -1; static char *arg_usr_what = NULL; static char *arg_usr_fstype = NULL; static char *arg_usr_options = NULL; +static char *arg_usr_hash = NULL; static VolatileMode arg_volatile_mode = _VOLATILE_MODE_INVALID; STATIC_DESTRUCTOR_REGISTER(arg_root_what, freep); @@ -59,6 +60,7 @@ STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep); STATIC_DESTRUCTOR_REGISTER(arg_usr_what, freep); STATIC_DESTRUCTOR_REGISTER(arg_usr_fstype, freep); STATIC_DESTRUCTOR_REGISTER(arg_usr_options, freep); +STATIC_DESTRUCTOR_REGISTER(arg_usr_hash, freep); static int write_options(FILE *f, const char *options) { _cleanup_free_ char *o = NULL; @@ -969,6 +971,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (!strextend_with_separator(&arg_usr_options, ",", value)) return log_oom(); + } else if (streq(key, "usrhash")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + return free_and_strdup_warn(&arg_usr_hash, value); + } else if (streq(key, "rw") && !value) arg_root_rw = true; else if (streq(key, "ro") && !value) @@ -997,24 +1006,35 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat return 0; } -static int determine_root(void) { - /* If we have a root hash but no root device then Verity is used, and we use the "root" DM device as root. */ +static int determine_device(char **what, const char *hash, const char *name) { - if (arg_root_what) + assert(what); + assert(name); + + /* If we have a hash but no device then Verity is used, and we use the DM device. */ + if (*what) return 0; - if (!arg_root_hash) + if (!hash) return 0; - arg_root_what = strdup("/dev/mapper/root"); - if (!arg_root_what) + *what = path_join("/dev/mapper/", name); + if (!*what) return log_oom(); - log_info("Using verity root device %s.", arg_root_what); + log_info("Using verity %s device %s.", name, *what); return 1; } +static int determine_root(void) { + return determine_device(&arg_root_what, arg_root_hash, "root"); +} + +static int determine_usr(void) { + return determine_device(&arg_usr_what, arg_usr_hash, "usr"); +} + static int run(const char *dest, const char *dest_early, const char *dest_late) { int r, r2 = 0, r3 = 0; @@ -1026,6 +1046,7 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m"); (void) determine_root(); + (void) determine_usr(); /* Always honour root= and usr= in the kernel command line if we are in an initrd */ if (in_initrd()) { diff --git a/src/veritysetup/veritysetup-generator.c b/src/veritysetup/veritysetup-generator.c index 13181b86ed..e38bd04159 100644 --- a/src/veritysetup/veritysetup-generator.c +++ b/src/veritysetup/veritysetup-generator.c @@ -22,53 +22,69 @@ #include "string-util.h" #include "unit-name.h" -#define SYSTEMD_VERITYSETUP_SERVICE "systemd-veritysetup@root.service" +#define SYSTEMD_VERITYSETUP_SERVICE_ROOT "systemd-veritysetup@root.service" +#define SYSTEMD_VERITYSETUP_SERVICE_USR "systemd-veritysetup@usr.service" static const char *arg_dest = NULL; static bool arg_enabled = true; static bool arg_read_veritytab = true; static const char *arg_veritytab = NULL; static char *arg_root_hash = NULL; -static char *arg_data_what = NULL; -static char *arg_hash_what = NULL; -static char *arg_options = NULL; +static char *arg_root_data_what = NULL; +static char *arg_root_hash_what = NULL; +static char *arg_root_options = NULL; +static char *arg_usr_hash = NULL; +static char *arg_usr_data_what = NULL; +static char *arg_usr_hash_what = NULL; +static char *arg_usr_options = NULL; STATIC_DESTRUCTOR_REGISTER(arg_root_hash, freep); -STATIC_DESTRUCTOR_REGISTER(arg_data_what, freep); -STATIC_DESTRUCTOR_REGISTER(arg_hash_what, freep); -STATIC_DESTRUCTOR_REGISTER(arg_options, freep); +STATIC_DESTRUCTOR_REGISTER(arg_root_data_what, freep); +STATIC_DESTRUCTOR_REGISTER(arg_root_hash_what, freep); +STATIC_DESTRUCTOR_REGISTER(arg_root_options, freep); +STATIC_DESTRUCTOR_REGISTER(arg_usr_hash, freep); +STATIC_DESTRUCTOR_REGISTER(arg_usr_data_what, freep); +STATIC_DESTRUCTOR_REGISTER(arg_usr_hash_what, freep); +STATIC_DESTRUCTOR_REGISTER(arg_usr_options, freep); + +static int create_device( + const char *name, + const char *service, + const char *hash, + const char *data_what, + const char *hash_what, + const char *options) { -static int create_device(void) { _cleanup_free_ char *u = NULL, *v = NULL, *d = NULL, *e = NULL, *u_escaped = NULL, *v_escaped = NULL, - *root_hash_escaped = NULL, *options_escaped = NULL; + *hash_escaped = NULL, *options_escaped = NULL; _cleanup_fclose_ FILE *f = NULL; - const char *to; + const char *to, *from; int r; + assert(name); + assert(service); + /* If all three pieces of information are missing, then verity is turned off */ - if (!arg_root_hash && !arg_data_what && !arg_hash_what) + if (!hash && !data_what && !hash_what) return 0; /* if one of them is missing however, the data is simply incomplete and this is an error */ - if (!arg_root_hash) - log_error("Verity information incomplete, root hash unspecified."); - if (!arg_data_what) - log_error("Verity information incomplete, root data device unspecified."); - if (!arg_hash_what) - log_error("Verity information incomplete, root hash device unspecified."); - - if (!arg_root_hash || !arg_data_what || !arg_hash_what) + if (!hash) + log_error("Verity information for %s incomplete, hash unspecified.", name); + if (!data_what) + log_error("Verity information for %s incomplete, data device unspecified.", name); + if (!hash_what) + log_error("Verity information for %s incomplete, hash device unspecified.", name); + + if (!hash || !data_what || !hash_what) return -EINVAL; - log_debug("Using root verity data device %s,\n" - " hash device %s,\n" - " options %s,\n" - " and root hash %s.", arg_data_what, arg_hash_what, arg_options, arg_root_hash); + log_debug("Using %s verity data device %s, hash device %s, options %s, and hash %s.", name, data_what, hash_what, options, hash); - u = fstab_node_to_udev_node(arg_data_what); + u = fstab_node_to_udev_node(data_what); if (!u) return log_oom(); - v = fstab_node_to_udev_node(arg_hash_what); + v = fstab_node_to_udev_node(hash_what); if (!v) return log_oom(); @@ -86,15 +102,15 @@ static int create_device(void) { if (r < 0) return log_error_errno(r, "Failed to generate unit name: %m"); - options_escaped = specifier_escape(strempty(arg_options)); + options_escaped = specifier_escape(strempty(options)); if (!options_escaped) return log_oom(); - root_hash_escaped = specifier_escape(arg_root_hash); - if (!root_hash_escaped) + hash_escaped = specifier_escape(hash); + if (!hash_escaped) return log_oom(); - r = generator_open_unit_file(arg_dest, NULL, SYSTEMD_VERITYSETUP_SERVICE, &f); + r = generator_open_unit_file(arg_dest, NULL, service, &f); if (r < 0) return r; @@ -112,25 +128,35 @@ static int create_device(void) { "\n[Service]\n" "Type=oneshot\n" "RemainAfterExit=yes\n" - "ExecStart=" ROOTLIBEXECDIR "/systemd-veritysetup attach root '%s' '%s' '%s' '%s'\n" - "ExecStop=" ROOTLIBEXECDIR "/systemd-veritysetup detach root\n", + "ExecStart=" ROOTLIBEXECDIR "/systemd-veritysetup attach '%s' '%s' '%s' '%s' '%s'\n" + "ExecStop=" ROOTLIBEXECDIR "/systemd-veritysetup detach '%s' \n", d, e, d, e, - u_escaped, v_escaped, root_hash_escaped, options_escaped); + name, u_escaped, v_escaped, hash_escaped, options_escaped, + name); r = fflush_and_check(f); if (r < 0) - return log_error_errno(r, "Failed to write file unit "SYSTEMD_VERITYSETUP_SERVICE": %m"); + return log_error_errno(r, "Failed to write file unit %s: %m", service); - to = strjoina(arg_dest, "/veritysetup.target.requires/" SYSTEMD_VERITYSETUP_SERVICE); + to = strjoina(arg_dest, "/veritysetup.target.requires/", service); + from = strjoina("../", service); (void) mkdir_parents(to, 0755); - if (symlink("../" SYSTEMD_VERITYSETUP_SERVICE, to) < 0) + if (symlink(from, to) < 0) return log_error_errno(errno, "Failed to create symlink %s: %m", to); return 0; } +static int create_root_device(void) { + return create_device("root", SYSTEMD_VERITYSETUP_SERVICE_ROOT, arg_root_hash, arg_root_data_what, arg_root_hash_what, arg_root_options); +} + +static int create_usr_device(void) { + return create_device("usr", SYSTEMD_VERITYSETUP_SERVICE_USR, arg_usr_hash, arg_usr_data_what, arg_usr_hash_what, arg_usr_options); +} + static int parse_proc_cmdline_item(const char *key, const char *value, void *data) { int r; @@ -164,7 +190,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (proc_cmdline_value_missing(key, value)) return 0; - r = free_and_strdup(&arg_data_what, value); + r = free_and_strdup(&arg_root_data_what, value); if (r < 0) return log_oom(); @@ -173,7 +199,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (proc_cmdline_value_missing(key, value)) return 0; - r = free_and_strdup(&arg_hash_what, value); + r = free_and_strdup(&arg_root_hash_what, value); if (r < 0) return log_oom(); @@ -182,7 +208,43 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat if (proc_cmdline_value_missing(key, value)) return 0; - r = free_and_strdup(&arg_options, value); + r = free_and_strdup(&arg_root_options, value); + if (r < 0) + return log_oom(); + + } else if (proc_cmdline_key_streq(key, "usrhash")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = free_and_strdup(&arg_usr_hash, value); + if (r < 0) + return log_oom(); + + } else if (proc_cmdline_key_streq(key, "systemd.verity_usr_data")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = free_and_strdup(&arg_usr_data_what, value); + if (r < 0) + return log_oom(); + + } else if (proc_cmdline_key_streq(key, "systemd.verity_usr_hash")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = free_and_strdup(&arg_usr_hash_what, value); + if (r < 0) + return log_oom(); + + } else if (proc_cmdline_key_streq(key, "systemd.verity_usr_options")) { + + if (proc_cmdline_value_missing(key, value)) + return 0; + + r = free_and_strdup(&arg_usr_options, value); if (r < 0) return log_oom(); @@ -191,47 +253,66 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat return 0; } -static int determine_devices(void) { +static int determine_device( + const char *name, + const char *hash, + char **data_what, + char **hash_what) { + + sd_id128_t data_uuid, verity_uuid; _cleanup_free_ void *m = NULL; - sd_id128_t root_uuid, verity_uuid; size_t l; int r; - /* Try to automatically derive the root data and hash device paths from the root hash */ + assert(name); + assert(data_what); + assert(hash_what); - if (!arg_root_hash) + if (!hash) return 0; - if (arg_data_what && arg_hash_what) + if (*data_what && *hash_what) return 0; - r = unhexmem(arg_root_hash, strlen(arg_root_hash), &m, &l); + r = unhexmem(hash, strlen(hash), &m, &l); if (r < 0) - return log_error_errno(r, "Failed to parse root hash: %s", arg_root_hash); + return log_error_errno(r, "Failed to parse hash: %s", hash); if (l < sizeof(sd_id128_t)) { - log_debug("Root hash is shorter than 128 bits (32 characters), ignoring for discovering verity partition."); + log_debug("Root hash for %s is shorter than 128 bits (32 characters), ignoring for discovering verity partition.", name); return 0; } - if (!arg_data_what) { - memcpy(&root_uuid, m, sizeof(root_uuid)); + if (!*data_what) { + memcpy(&data_uuid, m, sizeof(data_uuid)); - arg_data_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(root_uuid)); - if (!arg_data_what) + *data_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(data_uuid)); + if (!*data_what) return log_oom(); } - if (!arg_hash_what) { + if (!*hash_what) { memcpy(&verity_uuid, (uint8_t*) m + l - sizeof(verity_uuid), sizeof(verity_uuid)); - arg_hash_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(verity_uuid)); - if (!arg_hash_what) + *hash_what = path_join("/dev/disk/by-partuuid", ID128_TO_UUID_STRING(verity_uuid)); + if (!*hash_what) return log_oom(); } + log_info("Using data device %s and hash device %s for %s.", *data_what, *hash_what, name); + return 1; } +static int determine_devices(void) { + int r; + + r = determine_device("root", arg_root_hash, &arg_root_data_what, &arg_root_hash_what); + if (r < 0) + return r; + + return determine_device("usr", arg_usr_hash, &arg_usr_data_what, &arg_usr_hash_what); +} + static int create_disk( const char *name, const char *data_device, @@ -446,7 +527,11 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) if (r < 0) return r; - return create_device(); + r = create_root_device(); + if (r < 0) + return r; + + return create_usr_device(); } DEFINE_MAIN_GENERATOR_FUNCTION(run); |