]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
veritysetup-generator: generate service for usr device
authorMark Boudreau <mboudreaudalton@gmail.com>
Wed, 10 Nov 2021 00:38:29 +0000 (19:38 -0500)
committerMark Boudreau <mboudreaudalton@gmail.com>
Fri, 19 Nov 2021 20:53:36 +0000 (15:53 -0500)
If 'usrhash' is present as a kernel command line parameter, generate a
veritysetup service for usr.
Also recognize systemd.verity_usr_* parameters.

src/veritysetup/veritysetup-generator.c

index 13181b86ed82ee12c1eaddff68a0703fcfd64842..e38bd041595697fdff864a6dc7c2d01d7a86d49a 100644 (file)
 #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);