]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
dissect-image,execute: switch root hash/root hash sig storage to struct iovec
authorLennart Poettering <lennart@poettering.net>
Sat, 15 Nov 2025 06:42:12 +0000 (07:42 +0100)
committerLennart Poettering <lennart@poettering.net>
Sun, 16 Nov 2025 22:36:11 +0000 (23:36 +0100)
let's go one step further on our iovec'ification journey.

No change in behaviour, just rework to make struct iovec used
everywhere.

16 files changed:
src/core/dbus-execute.c
src/core/exec-invoke.c
src/core/execute-serialize.c
src/core/execute.c
src/core/execute.h
src/core/load-fragment.c
src/core/namespace.c
src/core/varlink-execute.c
src/dissect/dissect.c
src/gpt-auto-generator/gpt-auto-generator.c
src/mountfsd/mountwork.c
src/nspawn/nspawn.c
src/repart/repart.c
src/shared/dissect-image.c
src/shared/dissect-image.h
src/udev/udev-builtin-dissect_image.c

index 7c5e70d40776ffd18f9aaf1e5b5cfd96b125401c..a349c001611ccdb29a45a073c8e9caff4d2c8cb6 100644 (file)
@@ -772,7 +772,7 @@ static int property_get_root_hash(
         assert(property);
         assert(reply);
 
-        return sd_bus_message_append_array(reply, 'y', c->root_hash, c->root_hash_size);
+        return sd_bus_message_append_array(reply, 'y', c->root_hash.iov_base, c->root_hash.iov_len);
 }
 
 static int property_get_root_hash_sig(
@@ -790,7 +790,7 @@ static int property_get_root_hash_sig(
         assert(property);
         assert(reply);
 
-        return sd_bus_message_append_array(reply, 'y', c->root_hash_sig, c->root_hash_sig_size);
+        return sd_bus_message_append_array(reply, 'y', c->root_hash_sig.iov_base, c->root_hash_sig.iov_len);
 }
 
 static int property_get_root_image_options(
@@ -1915,35 +1915,30 @@ int bus_exec_context_set_transient_property(
         }
 
         if (streq(name, "RootHash")) {
-                const void *roothash_decoded;
-                size_t roothash_decoded_size;
+                struct iovec roothash_decoded;
 
-                r = sd_bus_message_read_array(message, 'y', &roothash_decoded, &roothash_decoded_size);
+                r = sd_bus_message_read_array(message, 'y', (const void**) &roothash_decoded.iov_base, &roothash_decoded.iov_len);
                 if (r < 0)
                         return r;
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-                        _cleanup_free_ char *encoded = NULL;
 
-                        if (roothash_decoded_size == 0) {
+                        if (!iovec_is_set(&roothash_decoded)) {
                                 c->root_hash_path = mfree(c->root_hash_path);
-                                c->root_hash = mfree(c->root_hash);
-                                c->root_hash_size = 0;
+                                iovec_done(&c->root_hash);
 
                                 unit_write_settingf(u, flags, name, "RootHash=");
                         } else {
-                                _cleanup_free_ void *p = NULL;
-
-                                encoded = hexmem(roothash_decoded, roothash_decoded_size);
+                                _cleanup_free_ char *encoded = hexmem(roothash_decoded.iov_base, roothash_decoded.iov_len);
                                 if (!encoded)
                                         return -ENOMEM;
 
-                                p = memdup(roothash_decoded, roothash_decoded_size);
-                                if (!p)
+                                _cleanup_(iovec_done) struct iovec p = {};
+                                if (!iovec_memdup(&roothash_decoded, &p))
                                         return -ENOMEM;
 
-                                free_and_replace(c->root_hash, p);
-                                c->root_hash_size = roothash_decoded_size;
+                                iovec_done(&c->root_hash);
+                                c->root_hash = TAKE_STRUCT(p);
                                 c->root_hash_path = mfree(c->root_hash_path);
 
                                 unit_write_settingf(u, flags, name, "RootHash=%s", encoded);
@@ -1954,43 +1949,35 @@ int bus_exec_context_set_transient_property(
         }
 
         if (streq(name, "RootHashPath")) {
-                c->root_hash_size = 0;
-                c->root_hash = mfree(c->root_hash);
-
+                iovec_done(&c->root_hash);
                 return bus_set_transient_path(u, "RootHash", &c->root_hash_path, message, flags, error);
         }
 
         if (streq(name, "RootHashSignature")) {
-                const void *roothash_sig_decoded;
-                size_t roothash_sig_decoded_size;
+                struct iovec roothash_sig_decoded;
 
-                r = sd_bus_message_read_array(message, 'y', &roothash_sig_decoded, &roothash_sig_decoded_size);
+                r = sd_bus_message_read_array(message, 'y', (const void**) &roothash_sig_decoded.iov_base, &roothash_sig_decoded.iov_len);
                 if (r < 0)
                         return r;
 
                 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
-                        _cleanup_free_ char *encoded = NULL;
-
-                        if (roothash_sig_decoded_size == 0) {
+                        if (!iovec_is_set(&roothash_sig_decoded)) {
                                 c->root_hash_sig_path = mfree(c->root_hash_sig_path);
-                                c->root_hash_sig = mfree(c->root_hash_sig);
-                                c->root_hash_sig_size = 0;
+                                iovec_done(&c->root_hash_sig);
 
                                 unit_write_settingf(u, flags, name, "RootHashSignature=");
                         } else {
-                                _cleanup_free_ void *p = NULL;
-                                ssize_t len;
-
-                                len = base64mem(roothash_sig_decoded, roothash_sig_decoded_size, &encoded);
+                                _cleanup_free_ char *encoded = NULL;
+                                ssize_t len = base64mem(roothash_sig_decoded.iov_base, roothash_sig_decoded.iov_len, &encoded);
                                 if (len < 0)
                                         return -ENOMEM;
 
-                                p = memdup(roothash_sig_decoded, roothash_sig_decoded_size);
-                                if (!p)
+                                _cleanup_(iovec_done) struct iovec p = {};
+                                if (!iovec_memdup(&roothash_sig_decoded, &p))
                                         return -ENOMEM;
 
-                                free_and_replace(c->root_hash_sig, p);
-                                c->root_hash_sig_size = roothash_sig_decoded_size;
+                                iovec_done(&c->root_hash_sig);
+                                c->root_hash_sig = TAKE_STRUCT(p);
                                 c->root_hash_sig_path = mfree(c->root_hash_sig_path);
 
                                 unit_write_settingf(u, flags, name, "RootHashSignature=base64:%s", encoded);
@@ -2001,9 +1988,7 @@ int bus_exec_context_set_transient_property(
         }
 
         if (streq(name, "RootHashSignaturePath")) {
-                c->root_hash_sig_size = 0;
-                c->root_hash_sig = mfree(c->root_hash_sig);
-
+                iovec_done(&c->root_hash_sig);
                 return bus_set_transient_path(u, "RootHashSignature", &c->root_hash_sig_path, message, flags, error);
         }
 
index 44823a881fa3e6284f9aaa1f4dae06b9ba3505f2..88178a82f96c6f09c98e4ae6ae6073dee87a179a 100644 (file)
@@ -3583,11 +3583,9 @@ static int setup_ephemeral(
 static int verity_settings_prepare(
                 VeritySettings *verity,
                 const char *root_image,
-                const void *root_hash,
-                size_t root_hash_size,
+                const struct iovec *root_hash,
                 const char *root_hash_path,
-                const void *root_hash_sig,
-                size_t root_hash_sig_size,
+                const struct iovec *root_hash_sig,
                 const char *root_hash_sig_path,
                 const char *verity_data_path) {
 
@@ -3596,26 +3594,20 @@ static int verity_settings_prepare(
         assert(verity);
 
         if (root_hash) {
-                void *d;
+                iovec_done(&verity->root_hash);
 
-                d = memdup(root_hash, root_hash_size);
-                if (!d)
+                if (!iovec_memdup(root_hash, &verity->root_hash))
                         return -ENOMEM;
 
-                free_and_replace(verity->root_hash, d);
-                verity->root_hash_size = root_hash_size;
                 verity->designator = PARTITION_ROOT;
         }
 
         if (root_hash_sig) {
-                void *d;
+                iovec_done(&verity->root_hash_sig);
 
-                d = memdup(root_hash_sig, root_hash_sig_size);
-                if (!d)
+                if (!iovec_memdup(root_hash_sig, &verity->root_hash_sig))
                         return -ENOMEM;
 
-                free_and_replace(verity->root_hash_sig, d);
-                verity->root_hash_sig_size = root_hash_sig_size;
                 verity->designator = PARTITION_ROOT;
         }
 
@@ -3845,8 +3837,8 @@ static int apply_mount_namespace(
                 r = verity_settings_prepare(
                         &verity,
                         root_image,
-                        context->root_hash, context->root_hash_size, context->root_hash_path,
-                        context->root_hash_sig, context->root_hash_sig_size, context->root_hash_sig_path,
+                        &context->root_hash, context->root_hash_path,
+                        &context->root_hash_sig, context->root_hash_sig_path,
                         context->root_verity);
                 if (r < 0)
                         return r;
index d046a8a6945d81bac6ed59d37db410e479a2c08c..f7a669d9c3b2307c52fd7f777ffc36635a8fb734 100644 (file)
@@ -1662,11 +1662,11 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) {
         if (r < 0)
                 return r;
 
-        r = serialize_item_hexmem(f, "exec-context-root-hash", c->root_hash, c->root_hash_size);
+        r = serialize_item_hexmem(f, "exec-context-root-hash", c->root_hash.iov_base, c->root_hash.iov_len);
         if (r < 0)
                 return r;
 
-        r = serialize_item_base64mem(f, "exec-context-root-hash-sig", c->root_hash_sig, c->root_hash_sig_size);
+        r = serialize_item_base64mem(f, "exec-context-root-hash-sig", c->root_hash_sig.iov_base, c->root_hash_sig.iov_len);
         if (r < 0)
                 return r;
 
@@ -2616,13 +2616,13 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
                         if (r < 0)
                                 return r;
                 } else if ((val = startswith(l, "exec-context-root-hash="))) {
-                        c->root_hash = mfree(c->root_hash);
-                        r = unhexmem(val, &c->root_hash, &c->root_hash_size);
+                        iovec_done(&c->root_hash);
+                        r = unhexmem(val, &c->root_hash.iov_base, &c->root_hash.iov_len);
                         if (r < 0)
                                 return r;
                 } else if ((val = startswith(l, "exec-context-root-hash-sig="))) {
-                        c->root_hash_sig = mfree(c->root_hash_sig);
-                        r= unbase64mem(val, &c->root_hash_sig, &c->root_hash_sig_size);
+                        iovec_done(&c->root_hash_sig);
+                        r= unbase64mem(val, &c->root_hash_sig.iov_base, &c->root_hash_sig.iov_len);
                         if (r < 0)
                                 return r;
                 } else if ((val = startswith(l, "exec-context-root-ephemeral="))) {
index bb74b6688367893c5fe5ad412c78b70643cad545..29a4f69291328fe0c04922a563ad650a7d403b07 100644 (file)
@@ -679,11 +679,9 @@ void exec_context_done(ExecContext *c) {
         c->root_directory = mfree(c->root_directory);
         c->root_image = mfree(c->root_image);
         c->root_image_options = mount_options_free_all(c->root_image_options);
-        c->root_hash = mfree(c->root_hash);
-        c->root_hash_size = 0;
+        iovec_done(&c->root_hash);
         c->root_hash_path = mfree(c->root_hash_path);
-        c->root_hash_sig = mfree(c->root_hash_sig);
-        c->root_hash_sig_size = 0;
+        iovec_done(&c->root_hash_sig);
         c->root_hash_sig_path = mfree(c->root_hash_sig_path);
         c->root_verity = mfree(c->root_verity);
         c->extension_images = mount_image_free_many(c->extension_images, &c->n_extension_images);
@@ -1178,9 +1176,9 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
                 fprintf(f, "\n");
         }
 
-        if (c->root_hash) {
+        if (iovec_is_set(&c->root_hash)) {
                 _cleanup_free_ char *encoded = NULL;
-                encoded = hexmem(c->root_hash, c->root_hash_size);
+                encoded = hexmem(c->root_hash.iov_base, c->root_hash.iov_len);
                 if (encoded)
                         fprintf(f, "%sRootHash: %s\n", prefix, encoded);
         }
@@ -1188,10 +1186,10 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
         if (c->root_hash_path)
                 fprintf(f, "%sRootHash: %s\n", prefix, c->root_hash_path);
 
-        if (c->root_hash_sig) {
+        if (iovec_is_set(&c->root_hash_sig)) {
                 _cleanup_free_ char *encoded = NULL;
                 ssize_t len;
-                len = base64mem(c->root_hash_sig, c->root_hash_sig_size, &encoded);
+                len = base64mem(c->root_hash_sig.iov_base, c->root_hash_sig.iov_len, &encoded);
                 if (len)
                         fprintf(f, "%sRootHashSignature: base64:%s\n", prefix, encoded);
         }
index dc150e65bc089d8f581b1572f3f55aafa25caa8d..62dd94e91d05ff9a789699b2e1e97cc953b8747b 100644 (file)
@@ -1,6 +1,8 @@
 /* SPDX-License-Identifier: LGPL-2.1-or-later */
 #pragma once
 
+#include <sys/uio.h>
+
 #include "sd-id128.h"
 
 #include "bus-unit-util.h"
@@ -181,8 +183,7 @@ typedef struct ExecContext {
 
         struct rlimit *rlimit[_RLIMIT_MAX];
         char *working_directory, *root_directory, *root_image, *root_verity, *root_hash_path, *root_hash_sig_path;
-        void *root_hash, *root_hash_sig;
-        size_t root_hash_size, root_hash_sig_size;
+        struct iovec root_hash, root_hash_sig;
         LIST_HEAD(MountOptions, root_image_options);
         bool root_ephemeral;
         bool working_directory_missing_ok:1;
index b9c6ea6439c71a305fe8d59d40f969c1242ff866..ca1ce53066d865b68128ae9e1a339376745a0dc3 100644 (file)
@@ -1714,9 +1714,7 @@ int config_parse_exec_root_hash(
                 void *data,
                 void *userdata) {
 
-        _cleanup_free_ void *roothash_decoded = NULL;
         ExecContext *c = ASSERT_PTR(data);
-        size_t roothash_decoded_size = 0;
         int r;
 
         assert(filename);
@@ -1726,8 +1724,7 @@ int config_parse_exec_root_hash(
         if (isempty(rvalue)) {
                 /* Reset if the empty string is assigned */
                 c->root_hash_path = mfree(c->root_hash_path);
-                c->root_hash = mfree(c->root_hash);
-                c->root_hash_size = 0;
+                iovec_done(&c->root_hash);
                 return 0;
         }
 
@@ -1740,24 +1737,24 @@ int config_parse_exec_root_hash(
                         return -ENOMEM;
 
                 free_and_replace(c->root_hash_path, p);
-                c->root_hash = mfree(c->root_hash);
-                c->root_hash_size = 0;
+                iovec_done(&c->root_hash);
                 return 0;
         }
 
         /* We have a roothash to decode, eg: RootHash=012345789abcdef */
-        r = unhexmem(rvalue, &roothash_decoded, &roothash_decoded_size);
+        _cleanup_(iovec_done) struct iovec roothash_decoded = {};
+        r = unhexmem(rvalue, &roothash_decoded.iov_base, &roothash_decoded.iov_len);
         if (r < 0) {
                 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to decode RootHash=, ignoring: %s", rvalue);
                 return 0;
         }
-        if (roothash_decoded_size < sizeof(sd_id128_t)) {
+        if (roothash_decoded.iov_len < sizeof(sd_id128_t)) {
                 log_syntax(unit, LOG_WARNING, filename, line, 0, "RootHash= is too short, ignoring: %s", rvalue);
                 return 0;
         }
 
-        free_and_replace(c->root_hash, roothash_decoded);
-        c->root_hash_size = roothash_decoded_size;
+        iovec_done(&c->root_hash);
+        c->root_hash = TAKE_STRUCT(roothash_decoded);
         c->root_hash_path = mfree(c->root_hash_path);
 
         return 0;
@@ -1775,10 +1772,7 @@ int config_parse_exec_root_hash_sig(
                 void *data,
                 void *userdata) {
 
-        _cleanup_free_ void *roothash_sig_decoded = NULL;
-        char *value;
         ExecContext *c = ASSERT_PTR(data);
-        size_t roothash_sig_decoded_size = 0;
         int r;
 
         assert(filename);
@@ -1788,8 +1782,7 @@ int config_parse_exec_root_hash_sig(
         if (isempty(rvalue)) {
                 /* Reset if the empty string is assigned */
                 c->root_hash_sig_path = mfree(c->root_hash_sig_path);
-                c->root_hash_sig = mfree(c->root_hash_sig);
-                c->root_hash_sig_size = 0;
+                iovec_done(&c->root_hash_sig);
                 return 0;
         }
 
@@ -1802,26 +1795,27 @@ int config_parse_exec_root_hash_sig(
                         return log_oom();
 
                 free_and_replace(c->root_hash_sig_path, p);
-                c->root_hash_sig = mfree(c->root_hash_sig);
-                c->root_hash_sig_size = 0;
+                iovec_done(&c->root_hash_sig);
                 return 0;
         }
 
-        if (!(value = startswith(rvalue, "base64:"))) {
+        const char *value = startswith(rvalue, "base64:");
+        if (!value) {
                 log_syntax(unit, LOG_WARNING, filename, line, 0,
                            "Failed to decode RootHashSignature=, not a path but doesn't start with 'base64:', ignoring: %s", rvalue);
                 return 0;
         }
 
         /* We have a roothash signature to decode, eg: RootHashSignature=base64:012345789abcdef */
-        r = unbase64mem(value, &roothash_sig_decoded, &roothash_sig_decoded_size);
+        _cleanup_(iovec_done) struct iovec roothash_sig_decoded = {};
+        r = unbase64mem(value, &roothash_sig_decoded.iov_base, &roothash_sig_decoded.iov_len);
         if (r < 0) {
                 log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to decode RootHashSignature=, ignoring: %s", rvalue);
                 return 0;
         }
 
-        free_and_replace(c->root_hash_sig, roothash_sig_decoded);
-        c->root_hash_sig_size = roothash_sig_decoded_size;
+        iovec_done(&c->root_hash_sig);
+        c->root_hash_sig = TAKE_STRUCT(roothash_sig_decoded);
         c->root_hash_sig_path = mfree(c->root_hash_sig_path);
 
         return 0;
index 07a69c03a6259f1ea214c674be94429a8a9f9a90..56c077b1628ff17582b1f70ee587047e82a63c18 100644 (file)
@@ -24,6 +24,7 @@
 #include "format-util.h"
 #include "fs-util.h"
 #include "glyph-util.h"
+#include "iovec-util.h"
 #include "label-util.h"
 #include "list.h"
 #include "lock-util.h"
@@ -1019,7 +1020,7 @@ static bool verity_has_later_duplicates(MountList *ml, const MountEntry *needle)
         assert(needle >= ml->mounts && needle < ml->mounts + ml->n_mounts);
         assert(needle->mode == MOUNT_EXTENSION_IMAGE);
 
-        if (needle->verity.root_hash_size == 0)
+        if (!iovec_is_set(&needle->verity.root_hash))
                 return false;
 
         /* Overlayfs rejects supplying the same directory inode twice as determined by filesystem UUID and
@@ -1032,10 +1033,7 @@ static bool verity_has_later_duplicates(MountList *ml, const MountEntry *needle)
         for (const MountEntry *m = needle + 1; m < ml->mounts + ml->n_mounts; m++) {
                 if (m->mode != MOUNT_EXTENSION_IMAGE)
                         continue;
-                if (memcmp_nn(m->verity.root_hash,
-                              m->verity.root_hash_size,
-                              needle->verity.root_hash,
-                              needle->verity.root_hash_size) == 0)
+                if (iovec_memcmp(&m->verity.root_hash, &needle->verity.root_hash) == 0)
                         return true;
         }
 
index c9c81152283418e4643a4e369c24fc753cc1d944..116d77e006d81969049cb91afe3c15667c4ff168 100644 (file)
@@ -790,9 +790,9 @@ int unit_exec_context_build_json(sd_json_variant **ret, const char *name, void *
                         JSON_BUILD_PAIR_STRING_NON_EMPTY("RootImage", c->root_image),
                         JSON_BUILD_PAIR_CALLBACK_NON_NULL("RootImageOptions", root_image_options_build_json, c->root_image_options),
                         SD_JSON_BUILD_PAIR_BOOLEAN("RootEphemeral", c->root_ephemeral),
-                        JSON_BUILD_PAIR_BASE64_NON_EMPTY("RootHash", c->root_hash, c->root_hash_size),
+                        JSON_BUILD_PAIR_BASE64_NON_EMPTY("RootHash", c->root_hash.iov_base, c->root_hash.iov_len),
                         JSON_BUILD_PAIR_STRING_NON_EMPTY("RootHashPath", c->root_hash_path),
-                        JSON_BUILD_PAIR_BASE64_NON_EMPTY("RootHashSignature", c->root_hash_sig, c->root_hash_sig_size),
+                        JSON_BUILD_PAIR_BASE64_NON_EMPTY("RootHashSignature", c->root_hash_sig.iov_base, c->root_hash_sig.iov_len),
                         JSON_BUILD_PAIR_STRING_NON_EMPTY("RootHashSignaturePath", c->root_hash_sig_path),
                         JSON_BUILD_PAIR_STRING_NON_EMPTY("RootVerity", c->root_verity),
                         SD_JSON_BUILD_PAIR_CALLBACK("RootImagePolicy", image_policy_build_json, c->root_image_policy),
index f4c02737f5ad8e6ca0e28acb2d33bbc40e0e16e4..1a8fa52fce8a118a0903e3ee513f9560aafa9e35 100644 (file)
@@ -474,23 +474,22 @@ static int parse_argv(int argc, char *argv[]) {
 
                 case ARG_ROOT_HASH:
                 case ARG_USR_HASH: {
-                        _cleanup_free_ void *p = NULL;
-                        size_t l;
+                        _cleanup_(iovec_done) struct iovec roothash = {};
 
                         PartitionDesignator d = c == ARG_USR_HASH ? PARTITION_USR : PARTITION_ROOT;
                         if (arg_verity_settings.designator >= 0 &&
                             arg_verity_settings.designator != d)
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot combine --root-hash=/--root-hash-sig= and --usr-hash=/--usr-hash-sig= options.");
 
-                        r = unhexmem(optarg, &p, &l);
+                        r = unhexmem(optarg, &roothash.iov_base, &roothash.iov_len);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to parse root hash '%s': %m", optarg);
-                        if (l < sizeof(sd_id128_t))
+                        if (roothash.iov_len < sizeof(sd_id128_t))
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                                        "Root hash must be at least 128-bit long: %s", optarg);
 
-                        free_and_replace(arg_verity_settings.root_hash, p);
-                        arg_verity_settings.root_hash_size = l;
+                        iovec_done(&arg_verity_settings.root_hash);
+                        arg_verity_settings.root_hash = TAKE_STRUCT(roothash);
                         arg_verity_settings.designator = d;
                         break;
                 }
@@ -498,8 +497,7 @@ static int parse_argv(int argc, char *argv[]) {
                 case ARG_ROOT_HASH_SIG:
                 case ARG_USR_HASH_SIG: {
                         char *value;
-                        size_t l;
-                        void *p;
+                        _cleanup_(iovec_done) struct iovec sig = {};
 
                         PartitionDesignator d = c == ARG_USR_HASH_SIG ? PARTITION_USR : PARTITION_ROOT;
                         if (arg_verity_settings.designator >= 0 &&
@@ -507,17 +505,17 @@ static int parse_argv(int argc, char *argv[]) {
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Cannot combine --root-hash=/--root-hash-sig= and --usr-hash=/--usr-hash-sig= options.");
 
                         if ((value = startswith(optarg, "base64:"))) {
-                                r = unbase64mem(value, &p, &l);
+                                r = unbase64mem(value, &sig.iov_base, &sig.iov_len);
                                 if (r < 0)
                                         return log_error_errno(r, "Failed to parse root hash signature '%s': %m", optarg);
                         } else {
-                                r = read_full_file(optarg, (char**) &p, &l);
+                                r = read_full_file(optarg, (char**) &sig.iov_base, &sig.iov_len);
                                 if (r < 0)
                                         return log_error_errno(r, "Failed to read root hash signature file '%s': %m", optarg);
                         }
 
-                        free_and_replace(arg_verity_settings.root_hash_sig, p);
-                        arg_verity_settings.root_hash_sig_size = l;
+                        iovec_done(&arg_verity_settings.root_hash_sig);
+                        arg_verity_settings.root_hash_sig = TAKE_STRUCT(sig);
                         arg_verity_settings.designator = d;
                         break;
                 }
index 78525f3836c38f4143b0bb792655bf1189e55cde..ac9b3456bb036a2b030cfe01357658b839d6fdae 100644 (file)
@@ -1191,8 +1191,8 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
 
                 arg_verity_settings.designator = PARTITION_ROOT;
 
-                free(arg_verity_settings.root_hash);
-                r = unhexmem(value, &arg_verity_settings.root_hash, &arg_verity_settings.root_hash_size);
+                iovec_done(&arg_verity_settings.root_hash);
+                r = unhexmem(value, &arg_verity_settings.root_hash.iov_base, &arg_verity_settings.root_hash.iov_len);
                 if (r < 0)
                         return log_error_errno(r, "Failed to parse roothash= from kernel command line: %m");
 
@@ -1203,8 +1203,8 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
 
                 arg_verity_settings.designator = PARTITION_USR;
 
-                free(arg_verity_settings.root_hash);
-                r = unhexmem(value, &arg_verity_settings.root_hash, &arg_verity_settings.root_hash_size);
+                iovec_done(&arg_verity_settings.root_hash);
+                r = unhexmem(value, &arg_verity_settings.root_hash.iov_base, &arg_verity_settings.root_hash.iov_len);
                 if (r < 0)
                         return log_error_errno(r, "Failed to parse usrhash= from kernel command line: %m");
 
index 32c0420ad00489c602f839b28589d4fa84848dca..2f12f02e7ba9a45d738c4ea34eab484d63d7ba89 100644 (file)
@@ -379,14 +379,8 @@ static int vl_method_mount_image(
                         return -ENOMEM;
 
                 verity.designator = PARTITION_ROOT;
-
-                verity.root_hash = TAKE_PTR(p.verity_root_hash.iov_base);
-                verity.root_hash_size = p.verity_root_hash.iov_len;
-                p.verity_root_hash.iov_len = 0;
-
-                verity.root_hash_sig = TAKE_PTR(p.verity_root_hash_sig.iov_base);
-                verity.root_hash_sig_size = p.verity_root_hash_sig.iov_len;
-                p.verity_root_hash_sig.iov_len = 0;
+                verity.root_hash = TAKE_STRUCT(p.verity_root_hash);
+                verity.root_hash_sig = TAKE_STRUCT(p.verity_root_hash_sig);
         }
 
         const char *polkit_details[] = {
index 000ac3cce6754aef4297158d61e7899933ecc8dd..2716a60d80c0f9901fde49bdc96c68c8c5497232 100644 (file)
@@ -1305,38 +1305,36 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_ROOT_HASH: {
-                        _cleanup_free_ void *k = NULL;
-                        size_t l;
+                        _cleanup_(iovec_done) struct iovec k = {};
 
-                        r = unhexmem(optarg, &k, &l);
+                        r = unhexmem(optarg, &k.iov_base, &k.iov_len);
                         if (r < 0)
                                 return log_error_errno(r, "Failed to parse root hash: %s", optarg);
-                        if (l < sizeof(sd_id128_t))
+                        if (k.iov_len < sizeof(sd_id128_t))
                                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Root hash must be at least 128-bit long: %s", optarg);
 
-                        free_and_replace(arg_verity_settings.root_hash, k);
-                        arg_verity_settings.root_hash_size = l;
+                        iovec_done(&arg_verity_settings.root_hash);
+                        arg_verity_settings.root_hash = TAKE_STRUCT(k);
                         break;
                 }
 
                 case ARG_ROOT_HASH_SIG: {
+                        _cleanup_(iovec_done) struct iovec p = {};
                         char *value;
-                        size_t l;
-                        void *p;
 
                         if ((value = startswith(optarg, "base64:"))) {
-                                r = unbase64mem(value, &p, &l);
+                                r = unbase64mem(value, &p.iov_base, &p.iov_len);
                                 if (r < 0)
                                         return log_error_errno(r, "Failed to parse root hash signature '%s': %m", optarg);
 
                         } else {
-                                r = read_full_file(optarg, (char**) &p, &l);
+                                r = read_full_file(optarg, (char**) &p.iov_base, &p.iov_len);
                                 if (r < 0)
                                         return log_error_errno(r, "Failed to parse root hash signature file '%s': %m", optarg);
                         }
 
-                        free_and_replace(arg_verity_settings.root_hash_sig, p);
-                        arg_verity_settings.root_hash_sig_size = l;
+                        iovec_done(&arg_verity_settings.root_hash_sig);
+                        arg_verity_settings.root_hash_sig = TAKE_STRUCT(p);
                         break;
                 }
 
@@ -6358,7 +6356,7 @@ static int run(int argc, char *argv[]) {
                                 goto finish;
                         }
 
-                        if (dissected_image->has_verity && !arg_verity_settings.root_hash)
+                        if (dissected_image->has_verity && !iovec_is_set(&arg_verity_settings.root_hash))
                                 log_notice("Note: image %s contains verity information, but no root hash specified and no embedded "
                                            "root hash signature found! Proceeding without integrity checking.", arg_image);
 
index 456aed41bd7f6d437f71656a8115c375aa23522e..698bbfab62c1d1e3fc8877590e87102dea1f4995 100644 (file)
@@ -5548,8 +5548,7 @@ static const VeritySettings *lookup_verity_settings_by_uuid_pair(sd_id128_t data
         memcpy(root_hash_key + sizeof(sd_id128_t), hash_uuid.bytes, sizeof(sd_id128_t));
 
         VeritySettings key = {
-                .root_hash = &root_hash_key,
-                .root_hash_size = sizeof(root_hash_key),
+                .root_hash = IOVEC_MAKE(root_hash_key, sizeof(root_hash_key)),
         };
 
         return set_get(arg_verity_settings, &key);
@@ -5557,10 +5556,8 @@ static const VeritySettings *lookup_verity_settings_by_uuid_pair(sd_id128_t data
 
 static int partition_format_verity_sig(Context *context, Partition *p) {
         _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
-        _cleanup_(iovec_done) struct iovec sig_free = {};
         _cleanup_free_ char *text = NULL, *hint = NULL;
         const VeritySettings *verity_settings;
-        struct iovec roothash, sig;
         Partition *hp, *rp;
         uint8_t fp[X509_FINGERPRINT_SIZE];
         int whole_fd, r;
@@ -5600,22 +5597,18 @@ static int partition_format_verity_sig(Context *context, Partition *p) {
 
         assert_se((whole_fd = fdisk_get_devfd(context->fdisk_context)) >= 0);
 
+        _cleanup_(iovec_done) struct iovec sig_free = {};
+        const struct iovec *roothash, *sig;
         if (verity_settings) {
-                sig = (struct iovec) {
-                        .iov_base = verity_settings->root_hash_sig,
-                        .iov_len = verity_settings->root_hash_sig_size,
-                };
-                roothash = (struct iovec) {
-                        .iov_base = verity_settings->root_hash,
-                        .iov_len = verity_settings->root_hash_size,
-                };
+                sig = &verity_settings->root_hash_sig;
+                roothash = &verity_settings->root_hash;
         } else {
                 r = sign_verity_roothash(context, &hp->roothash, &sig_free);
                 if (r < 0)
                         return r;
 
-                sig = sig_free;
-                roothash = hp->roothash;
+                sig = &sig_free;
+                roothash = &hp->roothash;
         }
 
 #if HAVE_OPENSSL
@@ -5627,9 +5620,9 @@ static int partition_format_verity_sig(Context *context, Partition *p) {
 
         r = sd_json_buildo(
                         &v,
-                        SD_JSON_BUILD_PAIR("rootHash", SD_JSON_BUILD_HEX(roothash.iov_base, roothash.iov_len)),
+                        SD_JSON_BUILD_PAIR("rootHash", SD_JSON_BUILD_HEX(roothash->iov_base, roothash->iov_len)),
                         SD_JSON_BUILD_PAIR_CONDITION(has_fp, "certificateFingerprint", SD_JSON_BUILD_HEX(fp, sizeof(fp))),
-                        SD_JSON_BUILD_PAIR("signature", JSON_BUILD_IOVEC_BASE64(&sig)));
+                        SD_JSON_BUILD_PAIR("signature", JSON_BUILD_IOVEC_BASE64(sig)));
         if (r < 0)
                 return log_error_errno(r, "Failed to build verity signature JSON object: %m");
 
@@ -8824,9 +8817,8 @@ static int parse_partition_types(const char *p, GptPartitionType **partitions, s
 static int parse_join_signature(const char *p, Set **verity_settings_map) {
         _cleanup_(verity_settings_freep) VeritySettings *verity_settings = NULL;
         _cleanup_free_ char *root_hash = NULL;
-        _cleanup_free_ void *content = NULL;
         const char *signature;
-        size_t len;
+        _cleanup_(iovec_done) struct iovec content = {};
         int r;
 
         assert(p);
@@ -8838,17 +8830,17 @@ static int parse_join_signature(const char *p, Set **verity_settings_map) {
         if (!p)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected hash:sig");
         if ((signature = startswith(p, "base64:"))) {
-                r = unbase64mem(signature, &content, &len);
+                r = unbase64mem(signature, &content.iov_base, &content.iov_len);
                 if (r < 0)
                         return log_error_errno(r, "Failed to parse root hash signature '%s': %m", signature);
         } else {
-                r = read_full_file(p, (char**) &content, &len);
+                r = read_full_file(p, (char**) &content.iov_base, &content.iov_len);
                 if (r < 0)
                         return log_error_errno(r, "Failed to read root hash signature file '%s': %m", p);
         }
-        if (len == 0)
+        if (!iovec_is_set(&content))
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Empty verity signature specified.");
-        if (len > VERITY_SIG_SIZE)
+        if (content.iov_len > VERITY_SIG_SIZE)
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Verity signatures larger than %llu are not allowed.",
                                        VERITY_SIG_SIZE);
@@ -8858,21 +8850,17 @@ static int parse_join_signature(const char *p, Set **verity_settings_map) {
                 return log_oom();
 
         *verity_settings = (VeritySettings) {
-                .root_hash_sig = TAKE_PTR(content),
-                .root_hash_sig_size = len,
+                .root_hash_sig = TAKE_STRUCT(content),
         };
 
-        r = unhexmem(root_hash, &content, &len);
+        r = unhexmem(root_hash, &verity_settings->root_hash.iov_base, &verity_settings->root_hash.iov_len);
         if (r < 0)
                 return log_error_errno(r, "Failed to parse root hash '%s': %m", root_hash);
-        if (len < sizeof(sd_id128_t))
+        if (verity_settings->root_hash.iov_len < sizeof(sd_id128_t))
                 return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
                                        "Root hash must be at least 128-bit long: %s",
                                        root_hash);
 
-        verity_settings->root_hash = TAKE_PTR(content);
-        verity_settings->root_hash_size = len;
-
         r = set_ensure_put(verity_settings_map, &verity_settings_hash_ops, verity_settings);
         if (r < 0)
                 return log_error_errno(r, "Failed to add entry to hashmap: %m");
index 1162982f71cfd5dc53ad2b95f55f9d2b89f3b8ab..ff59029f9f4235bd40ebd49f39e062d7bc3c4235 100644 (file)
@@ -47,6 +47,7 @@
 #include "image-policy.h"
 #include "import-util.h"
 #include "io-util.h"
+#include "iovec-util.h"
 #include "json-util.h"
 #include "loop-util.h"
 #include "mkdir-label.h"
@@ -572,16 +573,12 @@ static int acquire_sig_for_roothash(
                 int fd,
                 uint64_t partition_offset,
                 uint64_t partition_size,
-                void **ret_root_hash,
-                size_t *ret_root_hash_size,
-                void **ret_root_hash_sig,
-                size_t *ret_root_hash_sig_size) {
+                struct iovec *ret_root_hash,
+                struct iovec *ret_root_hash_sig) {
 
         int r;
 
         assert(fd >= 0);
-        assert(!!ret_root_hash == !!ret_root_hash_size);
-        assert(!!ret_root_hash_sig == !!ret_root_hash_sig_size);
 
         if (partition_offset == UINT64_MAX || partition_size == UINT64_MAX)
                 return -EINVAL;
@@ -616,9 +613,8 @@ static int acquire_sig_for_roothash(
         if (!rh)
                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Signature JSON object lacks 'rootHash' field.");
 
-        _cleanup_free_ void *root_hash = NULL;
-        size_t root_hash_size;
-        r = sd_json_variant_unhex(rh, &root_hash, &root_hash_size);
+        _cleanup_(iovec_done) struct iovec root_hash = {};
+        r = sd_json_variant_unhex(rh, &root_hash.iov_base, &root_hash.iov_len);
         if (r < 0)
                 return log_debug_errno(r, "Failed to parse root hash field: %m");
 
@@ -626,21 +622,16 @@ static int acquire_sig_for_roothash(
         if (!sig)
                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Signature JSON object lacks 'signature' field.");
 
-        _cleanup_free_ void *root_hash_sig = NULL;
-        size_t root_hash_sig_size;
-        r = sd_json_variant_unbase64(sig, &root_hash_sig, &root_hash_sig_size);
+        _cleanup_(iovec_done) struct iovec root_hash_sig = {};
+        r = sd_json_variant_unbase64(sig, &root_hash_sig.iov_base, &root_hash_sig.iov_len);
         if (r < 0)
                 return log_debug_errno(r, "Failed to parse signature field: %m");
 
-        if (ret_root_hash) {
-                *ret_root_hash = TAKE_PTR(root_hash);
-                *ret_root_hash_size = root_hash_size;
-        }
+        if (ret_root_hash)
+                *ret_root_hash = TAKE_STRUCT(root_hash);
 
-        if (ret_root_hash_sig) {
-                *ret_root_hash_sig = TAKE_PTR(root_hash_sig);
-                *ret_root_hash_sig_size = root_hash_sig_size;
-        }
+        if (ret_root_hash_sig)
+                *ret_root_hash_sig = TAKE_STRUCT(root_hash_sig);
 
         return 0;
 }
@@ -828,9 +819,9 @@ static int dissect_image(
         assert(fd >= 0);
         assert(devname);
         assert(!verity || verity->designator < 0 || IN_SET(verity->designator, PARTITION_ROOT, PARTITION_USR));
-        assert(!verity || verity->root_hash || verity->root_hash_size == 0);
-        assert(!verity || verity->root_hash_sig || verity->root_hash_sig_size == 0);
-        assert(!verity || (verity->root_hash || !verity->root_hash_sig));
+        assert(!verity || iovec_is_valid(&verity->root_hash));
+        assert(!verity || iovec_is_valid(&verity->root_hash_sig));
+        assert(!verity || iovec_is_set(&verity->root_hash) || !iovec_is_set(&verity->root_hash_sig));
         assert(!((flags & DISSECT_IMAGE_GPT_ONLY) && (flags & DISSECT_IMAGE_NO_PARTITION_TABLE)));
         assert(m->sector_size > 0);
 
@@ -849,18 +840,18 @@ static int dissect_image(
 
         uint64_t diskseq = m->loop ? m->loop->diskseq : 0;
 
-        if (verity && verity->root_hash) {
+        if (verity && iovec_is_set(&verity->root_hash)) {
                 sd_id128_t fsuuid, vuuid;
 
                 /* If a root hash is supplied, then we use the root partition that has a UUID that match the
                  * first 128-bit of the root hash. And we use the verity partition that has a UUID that match
                  * the final 128-bit. */
 
-                if (verity->root_hash_size < sizeof(sd_id128_t))
+                if (verity->root_hash.iov_len < sizeof(sd_id128_t))
                         return -EINVAL;
 
-                memcpy(&fsuuid, verity->root_hash, sizeof(sd_id128_t));
-                memcpy(&vuuid, (const uint8_t*) verity->root_hash + verity->root_hash_size - sizeof(sd_id128_t), sizeof(sd_id128_t));
+                memcpy(&fsuuid, verity->root_hash.iov_base, sizeof(sd_id128_t));
+                memcpy(&vuuid, (const uint8_t*) verity->root_hash.iov_base + verity->root_hash.iov_len - sizeof(sd_id128_t), sizeof(sd_id128_t));
 
                 if (sd_id128_is_null(fsuuid))
                         return -EINVAL;
@@ -955,7 +946,7 @@ static int dissect_image(
                         encrypted = streq_ptr(fstype, "crypto_LUKS");
 
                         if (verity_settings_data_covers(verity, PARTITION_ROOT))
-                                found_flags = verity->root_hash_sig_size > 0 ? PARTITION_POLICY_SIGNED : PARTITION_POLICY_VERITY;
+                                found_flags = iovec_is_set(&verity->root_hash_sig) ? PARTITION_POLICY_SIGNED : PARTITION_POLICY_VERITY;
                         else
                                 found_flags = encrypted ? PARTITION_POLICY_ENCRYPTED : PARTITION_POLICY_UNPROTECTED;
 
@@ -990,7 +981,7 @@ static int dissect_image(
                         m->verity_ready = verity_settings_data_covers(verity, PARTITION_ROOT);
 
                         m->has_verity_sig = false; /* signature not embedded, must be specified */
-                        m->verity_sig_ready = m->verity_ready && verity->root_hash_sig;
+                        m->verity_sig_ready = m->verity_ready && iovec_is_set(&verity->root_hash);
 
                         m->image_uuid = uuid;
 
@@ -1236,26 +1227,23 @@ static int dissect_image(
                                 rw = false;
 
                         } else if (type.designator == PARTITION_ROOT_VERITY_SIG) {
-                                if (verity && verity->root_hash) {
-                                        _cleanup_free_ void *root_hash = NULL;
-                                        size_t root_hash_size;
+                                if (verity && iovec_is_set(&verity->root_hash)) {
+                                        _cleanup_(iovec_done) struct iovec root_hash = {};
 
                                         r = acquire_sig_for_roothash(
                                                         fd,
                                                         start * 512,
                                                         size * 512,
                                                         &root_hash,
-                                                        &root_hash_size,
-                                                        /* ret_root_hash_sig= */ NULL,
-                                                        /* ret_root_hash_sig_size= */ NULL);
+                                                        /* ret_root_hash_sig= */ NULL);
                                         if (r < 0)
                                                 return r;
-                                        if (memcmp_nn(verity->root_hash, verity->root_hash_size, root_hash, root_hash_size) != 0) {
+                                        if (iovec_memcmp(&verity->root_hash, &root_hash) != 0) {
                                                 if (DEBUG_LOGGING) {
                                                         _cleanup_free_ char *found = NULL, *expected = NULL;
 
-                                                        found = hexmem(root_hash, root_hash_size);
-                                                        expected = hexmem(verity->root_hash, verity->root_hash_size);
+                                                        found = hexmem(root_hash.iov_base, root_hash.iov_len);
+                                                        expected = hexmem(verity->root_hash.iov_base, verity->root_hash.iov_len);
 
                                                         log_debug("Root hash in signature JSON data (%s) doesn't match configured hash (%s).", strna(found), strna(expected));
                                                 }
@@ -1305,26 +1293,23 @@ static int dissect_image(
                                 rw = false;
 
                         } else if (type.designator == PARTITION_USR_VERITY_SIG) {
-                                if (verity && verity->root_hash) {
-                                        _cleanup_free_ void *root_hash = NULL;
-                                        size_t root_hash_size;
+                                if (verity && iovec_is_set(&verity->root_hash)) {
+                                        _cleanup_(iovec_done) struct iovec root_hash = {};
 
                                         r = acquire_sig_for_roothash(
                                                         fd,
                                                         start * 512,
                                                         size * 512,
                                                         &root_hash,
-                                                        &root_hash_size,
-                                                        /* ret_root_hash_sig= */ NULL,
-                                                        /* ret_root_hash_sig_size= */ NULL);
+                                                        /* ret_root_hash_sig= */ NULL);
                                         if (r < 0)
                                                 return r;
-                                        if (memcmp_nn(verity->root_hash, verity->root_hash_size, root_hash, root_hash_size) != 0) {
+                                        if (iovec_memcmp(&verity->root_hash, &root_hash) != 0) {
                                                 if (DEBUG_LOGGING) {
                                                         _cleanup_free_ char *found = NULL, *expected = NULL;
 
-                                                        found = hexmem(root_hash, root_hash_size);
-                                                        expected = hexmem(verity->root_hash, verity->root_hash_size);
+                                                        found = hexmem(root_hash.iov_base, root_hash.iov_len);
+                                                        expected = hexmem(verity->root_hash.iov_base, verity->root_hash.iov_len);
 
                                                         log_debug("Root hash in signature JSON data (%s) doesn't match configured hash (%s).", strna(found), strna(expected));
                                                 }
@@ -1609,7 +1594,7 @@ static int dissect_image(
         if (!m->partitions[PARTITION_ROOT].found &&
             !m->partitions[PARTITION_USR].found &&
             (flags & DISSECT_IMAGE_GENERIC_ROOT) &&
-            (!verity || !verity->root_hash || verity->designator != PARTITION_USR)) {
+            (!verity || !iovec_is_set(&verity->root_hash) || verity->designator != PARTITION_USR)) {
 
                 /* OK, we found nothing usable, then check if there's a single generic partition, and use
                  * that. If the root hash was set however, then we won't fall back to a generic node, because
@@ -1694,7 +1679,7 @@ static int dissect_image(
                                 partition_designator_to_string(verity->designator),
                                 partition_designator_to_string(verity->designator));
 
-                if (verity->root_hash) {
+                if (iovec_is_set(&verity->root_hash)) {
                         /* If we have an explicit root hash and found the partitions for it, then we are ready to use
                          * Verity, set things up for it */
 
@@ -1730,7 +1715,7 @@ static int dissect_image(
 
                         m->verity_ready = true;
 
-                        if (verity->root_hash_sig)
+                        if (iovec_is_set(&verity->root_hash_sig))
                                 m->verity_sig_ready = true;
                 }
         }
@@ -2767,10 +2752,8 @@ static int verity_can_reuse(
                 struct crypt_device **ret_cd) {
 
         /* If the same volume was already open, check that the root hashes match, and reuse it if they do */
-        _cleanup_free_ char *root_hash_existing = NULL;
         _cleanup_(sym_crypt_freep) struct crypt_device *cd = NULL;
         struct crypt_params_verity crypt_params = {};
-        size_t root_hash_existing_size;
         int r;
 
         assert(verity);
@@ -2787,22 +2770,23 @@ static int verity_can_reuse(
         if (r < 0)
                 return log_debug_errno(r, "Error opening verity device, crypt_get_verity_info failed: %m");
 
-        root_hash_existing_size = verity->root_hash_size;
-        root_hash_existing = malloc0(root_hash_existing_size);
-        if (!root_hash_existing)
+        _cleanup_(iovec_done) struct iovec root_hash_existing = {
+                .iov_base = malloc0(verity->root_hash.iov_len),
+                .iov_len = verity->root_hash.iov_len,
+        };
+        if (!root_hash_existing.iov_base)
                 return -ENOMEM;
 
-        r = sym_crypt_volume_key_get(cd, CRYPT_ANY_SLOT, root_hash_existing, &root_hash_existing_size, NULL, 0);
+        r = sym_crypt_volume_key_get(cd, CRYPT_ANY_SLOT, root_hash_existing.iov_base, &root_hash_existing.iov_len, NULL, 0);
         if (r < 0)
                 return log_debug_errno(r, "Error opening verity device, crypt_volume_key_get failed: %m");
-        if (verity->root_hash_size != root_hash_existing_size ||
-            memcmp(root_hash_existing, verity->root_hash, verity->root_hash_size) != 0)
+        if (iovec_memcmp(&verity->root_hash, &root_hash_existing) != 0)
                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Error opening verity device, it already exists but root hashes are different.");
 
         /* Ensure that, if signatures are supported, we only reuse the device if the previous mount used the
          * same settings, so that a previous unsigned mount will not be reused if the user asks to use
          * signing for the new one, and vice versa. */
-        if (!!verity->root_hash_sig != !!(crypt_params.flags & CRYPT_VERITY_ROOT_HASH_SIGNATURE))
+        if (iovec_is_set(&verity->root_hash_sig) != FLAGS_SET(crypt_params.flags, CRYPT_VERITY_ROOT_HASH_SIGNATURE))
                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Error opening verity device, it already exists but signature settings are not the same.");
 
         *ret_cd = TAKE_PTR(cd);
@@ -2856,11 +2840,9 @@ static int validate_signature_userspace(const VeritySettings *verity, DissectIma
         _cleanup_free_ char *s = NULL;
         _cleanup_(BIO_freep) BIO *bio = NULL; /* 'bio' must be freed first, 's' second, hence keep this order
                                                * of declaration in place, please */
-        const unsigned char *d;
-
         assert(verity);
-        assert(verity->root_hash);
-        assert(verity->root_hash_sig);
+        assert(iovec_is_set(&verity->root_hash));
+        assert(iovec_is_set(&verity->root_hash_sig));
 
         /* Because installing a signature certificate into the kernel chain is so messy, let's optionally do
          * userspace validation. */
@@ -2873,12 +2855,12 @@ static int validate_signature_userspace(const VeritySettings *verity, DissectIma
                 return 0;
         }
 
-        d = verity->root_hash_sig;
-        p7 = d2i_PKCS7(NULL, &d, (long) verity->root_hash_sig_size);
+        const unsigned char *d = verity->root_hash_sig.iov_base;
+        p7 = d2i_PKCS7(NULL, &d, (long) verity->root_hash_sig.iov_len);
         if (!p7)
                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse PKCS7 DER signature data.");
 
-        s = hexmem(verity->root_hash, verity->root_hash_size);
+        s = hexmem(verity->root_hash.iov_base, verity->root_hash.iov_len);
         if (!s)
                 return log_oom_debug();
 
@@ -2939,7 +2921,7 @@ static int do_crypt_activate_verity(
         assert(name);
         assert(verity);
 
-        if (verity->root_hash_sig && FLAGS_SET(policy_flags, PARTITION_POLICY_SIGNED)) {
+        if (iovec_is_set(&verity->root_hash_sig) && FLAGS_SET(policy_flags, PARTITION_POLICY_SIGNED)) {
                 r = secure_getenv_bool("SYSTEMD_DISSECT_VERITY_SIGNATURE");
                 if (r < 0 && r != -ENXIO)
                         log_debug_errno(r, "Failed to parse $SYSTEMD_DISSECT_VERITY_SIGNATURE");
@@ -2953,10 +2935,10 @@ static int do_crypt_activate_verity(
                 r = sym_crypt_activate_by_signed_key(
                                 cd,
                                 name,
-                                verity->root_hash,
-                                verity->root_hash_size,
-                                verity->root_hash_sig,
-                                verity->root_hash_sig_size,
+                                verity->root_hash.iov_base,
+                                verity->root_hash.iov_len,
+                                verity->root_hash_sig.iov_base,
+                                verity->root_hash_sig.iov_len,
                                 CRYPT_ACTIVATE_READONLY);
                 if (r >= 0) {
                         log_debug("Verity activation via kernel signature logic worked.");
@@ -3000,8 +2982,8 @@ static int do_crypt_activate_verity(
         r = sym_crypt_activate_by_volume_key(
                         cd,
                         name,
-                        verity->root_hash,
-                        verity->root_hash_size,
+                        verity->root_hash.iov_base,
+                        verity->root_hash.iov_len,
                         CRYPT_ACTIVATE_READONLY);
         if (r < 0)
                 return log_debug_errno(r, "Activation of Verity via root hash failed: %m");
@@ -3049,7 +3031,7 @@ static int verity_partition(
         assert(m);
         assert(v || (verity && verity->data_path));
 
-        if (!verity || !verity->root_hash)
+        if (!verity || !iovec_is_set(&verity->root_hash))
                 return 0;
         if (!((verity->designator < 0 && designator == PARTITION_ROOT) ||
               (verity->designator == designator)))
@@ -3078,7 +3060,7 @@ static int verity_partition(
                 /* Use the roothash, which is unique per volume, as the device node name, so that it can be reused */
                 _cleanup_free_ char *root_hash_encoded = NULL;
 
-                root_hash_encoded = hexmem(verity->root_hash, verity->root_hash_size);
+                root_hash_encoded = hexmem(verity->root_hash.iov_base, verity->root_hash.iov_len);
                 if (!root_hash_encoded)
                         return -ENOMEM;
 
@@ -3246,7 +3228,8 @@ int dissected_image_decrypt(
         int r;
 
         assert(m);
-        assert(!verity || verity->root_hash || verity->root_hash_size == 0);
+        assert(!verity || iovec_is_valid(&verity->root_hash));
+        assert(!verity || iovec_is_valid(&verity->root_hash_sig));
 
         /* Returns:
          *
@@ -3260,7 +3243,7 @@ int dissected_image_decrypt(
          *      -EEXIST       â†’ DM device already exists under the specified name
          */
 
-        if (verity && verity->root_hash && verity->root_hash_size < sizeof(sd_id128_t))
+        if (verity && iovec_is_set(&verity->root_hash) && verity->root_hash.iov_len < sizeof(sd_id128_t))
                 return -EINVAL;
 
         if (!m->encrypted && !m->verity_ready)
@@ -3487,12 +3470,8 @@ static char *build_auxiliary_path(const char *image, const char *suffix) {
 void verity_settings_done(VeritySettings *v) {
         assert(v);
 
-        v->root_hash = mfree(v->root_hash);
-        v->root_hash_size = 0;
-
-        v->root_hash_sig = mfree(v->root_hash_sig);
-        v->root_hash_sig_size = 0;
-
+        iovec_done(&v->root_hash);
+        iovec_done(&v->root_hash_sig);
         v->data_path = mfree(v->data_path);
 }
 
@@ -3507,18 +3486,15 @@ VeritySettings* verity_settings_free(VeritySettings *v) {
 void verity_settings_hash_func(const VeritySettings *s, struct siphash *state) {
         assert(s);
 
-        siphash24_compress_typesafe(s->root_hash_size, state);
-        siphash24_compress(s->root_hash, s->root_hash_size, state);
+        siphash24_compress_typesafe(s->root_hash.iov_len, state);
+        siphash24_compress(s->root_hash.iov_base, s->root_hash.iov_len, state);
 }
 
 int verity_settings_compare_func(const VeritySettings *x, const VeritySettings *y) {
-        int r;
+        assert(x);
+        assert(y);
 
-        r = CMP(x->root_hash_size, y->root_hash_size);
-        if (r != 0)
-                return r;
-
-        return memcmp(x->root_hash, y->root_hash, x->root_hash_size);
+        return iovec_memcmp(&x->root_hash, &y->root_hash);
 }
 
 DEFINE_HASH_OPS_WITH_VALUE_DESTRUCTOR(verity_settings_hash_ops, VeritySettings, verity_settings_hash_func, verity_settings_compare_func, VeritySettings, verity_settings_free);
@@ -3529,9 +3505,6 @@ int verity_settings_load(
                 const char *root_hash_path,
                 const char *root_hash_sig_path) {
 
-        _cleanup_free_ void *root_hash = NULL, *root_hash_sig = NULL;
-        size_t root_hash_size = 0, root_hash_sig_size = 0;
-        _cleanup_free_ char *verity_data_path = NULL;
         PartitionDesignator designator;
         int r;
 
@@ -3553,7 +3526,8 @@ int verity_settings_load(
 
         /* We only fill in what isn't already filled in */
 
-        if (!verity->root_hash) {
+        _cleanup_(iovec_done) struct iovec root_hash = {};
+        if (!iovec_is_set(&verity->root_hash)) {
                 _cleanup_free_ char *text = NULL;
 
                 if (root_hash_path) {
@@ -3620,20 +3594,24 @@ int verity_settings_load(
                 }
 
                 if (text) {
-                        r = unhexmem(text, &root_hash, &root_hash_size);
+                        r = unhexmem(text, &root_hash.iov_base, &root_hash.iov_len);
                         if (r < 0)
                                 return r;
-                        if (root_hash_size < sizeof(sd_id128_t))
+                        if (root_hash.iov_len < sizeof(sd_id128_t))
                                 return -EINVAL;
                 }
         }
 
-        if ((root_hash || verity->root_hash) && !verity->root_hash_sig) {
+        _cleanup_(iovec_done) struct iovec root_hash_sig = {};
+        if ((iovec_is_set(&root_hash) || iovec_is_set(&verity->root_hash)) && !iovec_is_set(&verity->root_hash_sig)) {
                 if (root_hash_sig_path) {
-                        r = read_full_file(root_hash_sig_path, (char**) &root_hash_sig, &root_hash_sig_size);
+                        r = read_full_file(root_hash_sig_path, (char**) &root_hash_sig.iov_base, &root_hash_sig.iov_len);
                         if (r < 0 && r != -ENOENT)
                                 return r;
 
+                        if (r >= 0 && root_hash_sig.iov_len == 0) /* refuse empty size signatures */
+                                return -EINVAL;
+
                         if (designator < 0)
                                 designator = PARTITION_ROOT;
                 } else {
@@ -3646,32 +3624,36 @@ int verity_settings_load(
                                 if (!p)
                                         return -ENOMEM;
 
-                                r = read_full_file(p, (char**) &root_hash_sig, &root_hash_sig_size);
+                                r = read_full_file(p, (char**) &root_hash_sig.iov_base, &root_hash_sig.iov_len);
                                 if (r < 0 && r != -ENOENT)
                                         return r;
-                                if (r >= 0)
+                                if (r >= 0) {
                                         designator = PARTITION_ROOT;
+                                        if (root_hash_sig.iov_len == 0) /* refuse empty size signatures */
+                                                return -EINVAL;
+                                }
                         }
 
-                        if (!root_hash_sig && (designator < 0 || designator == PARTITION_USR)) {
+                        if (!iovec_is_set(&root_hash_sig) && (designator < 0 || designator == PARTITION_USR)) {
                                 _cleanup_free_ char *p = NULL;
 
                                 p = build_auxiliary_path(image, ".usrhash.p7s");
                                 if (!p)
                                         return -ENOMEM;
 
-                                r = read_full_file(p, (char**) &root_hash_sig, &root_hash_sig_size);
+                                r = read_full_file(p, (char**) &root_hash_sig.iov_base, &root_hash_sig.iov_len);
                                 if (r < 0 && r != -ENOENT)
                                         return r;
-                                if (r >= 0)
+                                if (r >= 0) {
                                         designator = PARTITION_USR;
+                                        if (root_hash_sig.iov_len == 0) /* refuse empty size signatures */
+                                                return -EINVAL;
+                                }
                         }
                 }
-
-                if (root_hash_sig && root_hash_sig_size == 0) /* refuse empty size signatures */
-                        return -EINVAL;
         }
 
+        _cleanup_free_ char *verity_data_path = NULL;
         if (!verity->data_path) {
                 _cleanup_free_ char *p = NULL;
 
@@ -3686,15 +3668,11 @@ int verity_settings_load(
                         verity_data_path = TAKE_PTR(p);
         }
 
-        if (root_hash) {
-                verity->root_hash = TAKE_PTR(root_hash);
-                verity->root_hash_size = root_hash_size;
-        }
+        if (iovec_is_set(&root_hash))
+                verity->root_hash = TAKE_STRUCT(root_hash);
 
-        if (root_hash_sig) {
-                verity->root_hash_sig = TAKE_PTR(root_hash_sig);
-                verity->root_hash_sig_size = root_hash_sig_size;
-        }
+        if (iovec_is_set(&root_hash_sig))
+                verity->root_hash_sig = TAKE_STRUCT(root_hash_sig);
 
         if (verity_data_path)
                 verity->data_path = TAKE_PTR(verity_data_path);
@@ -3713,17 +3691,15 @@ int verity_settings_copy(VeritySettings *dest, const VeritySettings *source) {
                 return 0;
         }
 
-        _cleanup_free_ void *rh = NULL;
-        if (source->root_hash_size > 0) {
-                rh = memdup(source->root_hash, source->root_hash_size);
-                if (!rh)
+        _cleanup_(iovec_done) struct iovec rh = {};
+        if (iovec_is_set(&source->root_hash)) {
+                if (!iovec_memdup(&source->root_hash, &rh))
                         return log_oom_debug();
         }
 
-        _cleanup_free_ void *sig = NULL;
-        if (source->root_hash_sig_size > 0) {
-                sig = memdup(source->root_hash_sig, source->root_hash_sig_size);
-                if (!sig)
+        _cleanup_(iovec_done) struct iovec sig = {};
+        if (iovec_is_set(&source->root_hash_sig)) {
+                if (!iovec_memdup(&source->root_hash_sig, &sig))
                         return log_oom_debug();
         }
 
@@ -3735,10 +3711,8 @@ int verity_settings_copy(VeritySettings *dest, const VeritySettings *source) {
         }
 
         *dest = (VeritySettings) {
-                .root_hash = TAKE_PTR(rh),
-                .root_hash_size = source->root_hash_size,
-                .root_hash_sig = TAKE_PTR(sig),
-                .root_hash_sig_size = source->root_hash_sig_size,
+                .root_hash = TAKE_STRUCT(rh),
+                .root_hash_sig = TAKE_STRUCT(sig),
                 .data_path = TAKE_PTR(p),
                 .designator = source->designator,
         };
@@ -3757,7 +3731,7 @@ int dissected_image_load_verity_sig_partition(
         assert(fd >= 0);
         assert(verity);
 
-        if (verity->root_hash && verity->root_hash_sig) /* Already loaded? */
+        if (iovec_is_set(&verity->root_hash) && iovec_is_set(&verity->root_hash_sig)) /* Already loaded? */
                 return 0;
 
         r = secure_getenv_bool("SYSTEMD_DISSECT_VERITY_EMBEDDED");
@@ -3791,29 +3765,32 @@ int dissected_image_load_verity_sig_partition(
         if (!p->found)
                 return 0;
 
-        _cleanup_free_ void *root_hash = NULL, *root_hash_sig = NULL;
-        size_t root_hash_size, root_hash_sig_size;
-
-        r = acquire_sig_for_roothash(fd, p->offset, p->size, &root_hash, &root_hash_size, &root_hash_sig, &root_hash_sig_size);
+        _cleanup_(iovec_done) struct iovec root_hash = {}, root_hash_sig = {};
+        r = acquire_sig_for_roothash(
+                        fd,
+                        p->offset,
+                        p->size,
+                        &root_hash,
+                        &root_hash_sig);
         if (r < 0)
                 return r;
 
         /* Check if specified root hash matches if it is specified */
-        if (verity->root_hash &&
-            memcmp_nn(verity->root_hash, verity->root_hash_size, root_hash, root_hash_size) != 0) {
+        if (iovec_is_set(&verity->root_hash) &&
+            iovec_memcmp(&verity->root_hash, &root_hash) != 0) {
                 _cleanup_free_ char *a = NULL, *b = NULL;
 
-                a = hexmem(root_hash, root_hash_size);
-                b = hexmem(verity->root_hash, verity->root_hash_size);
+                a = hexmem(root_hash.iov_base, root_hash.iov_len);
+                b = hexmem(verity->root_hash.iov_base, verity->root_hash.iov_len);
 
                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Root hash in signature JSON data (%s) doesn't match configured hash (%s).", strna(a), strna(b));
         }
 
-        free_and_replace(verity->root_hash, root_hash);
-        verity->root_hash_size = root_hash_size;
+        iovec_done(&verity->root_hash);
+        verity->root_hash = TAKE_STRUCT(root_hash);
 
-        free_and_replace(verity->root_hash_sig, root_hash_sig);
-        verity->root_hash_sig_size = root_hash_sig_size;
+        iovec_done(&verity->root_hash_sig);
+        verity->root_hash_sig = TAKE_STRUCT(root_hash_sig);
 
         verity->designator = dd;
 
@@ -3841,7 +3818,7 @@ int dissected_image_guess_verity_roothash(
          * Note of course that relying on this guesswork is mostly useful for later attestation, not so much
          * for a-priori security. */
 
-        if (verity->root_hash) /* Already loaded? */
+        if (iovec_is_set(&verity->root_hash)) /* Already loaded? */
                 return 0;
 
         r = secure_getenv_bool("SYSTEMD_DISSECT_VERITY_GUESS");
@@ -3871,13 +3848,12 @@ int dissected_image_guess_verity_roothash(
         if (!p->found)
                 return 0;
 
-        _cleanup_free_ uint8_t *rh = malloc(sizeof(sd_id128_t) * 2);
+        _cleanup_free_ void *rh = malloc(sizeof(sd_id128_t) * 2);
         if (!rh)
                 return log_oom_debug();
 
         memcpy(mempcpy(rh, &d->uuid, sizeof(sd_id128_t)), &p->uuid, sizeof(sd_id128_t));
-        verity->root_hash = TAKE_PTR(rh);
-        verity->root_hash_size = sizeof(sd_id128_t) * 2;
+        verity->root_hash = IOVEC_MAKE(TAKE_PTR(rh), sizeof(sd_id128_t) * 2);
 
         verity->designator = dd;
 
@@ -4838,8 +4814,8 @@ int mountfsd_mount_image(
                         SD_JSON_BUILD_PAIR_CONDITION(!!ps, "imagePolicy", SD_JSON_BUILD_STRING(ps)),
                         SD_JSON_BUILD_PAIR("veritySharing", SD_JSON_BUILD_BOOLEAN(FLAGS_SET(flags, DISSECT_IMAGE_VERITY_SHARE))),
                         SD_JSON_BUILD_PAIR_CONDITION(verity_data_fd >= 0, "verityDataFileDescriptor", SD_JSON_BUILD_UNSIGNED(userns_fd >= 0 ? 2 : 1)),
-                        JSON_BUILD_PAIR_IOVEC_HEX("verityRootHash", &((struct iovec) { .iov_base = verity->root_hash, .iov_len = verity->root_hash_size })),
-                        JSON_BUILD_PAIR_IOVEC_BASE64("verityRootHashSignature", &((struct iovec) { .iov_base = verity->root_hash_sig, .iov_len = verity->root_hash_sig_size })),
+                        JSON_BUILD_PAIR_IOVEC_HEX("verityRootHash", &verity->root_hash),
+                        JSON_BUILD_PAIR_IOVEC_BASE64("verityRootHashSignature", &verity->root_hash_sig),
                         SD_JSON_BUILD_PAIR("allowInteractiveAuthentication", SD_JSON_BUILD_BOOLEAN(FLAGS_SET(flags, DISSECT_IMAGE_ALLOW_INTERACTIVE_AUTH))));
         if (r < 0)
                 return r;
index 48d235996018a22770a56f7b0eb41756e2d9fadc..0e9732a923f176f59459a485f5d46c584399884b 100644 (file)
@@ -4,9 +4,10 @@
 #include "sd-id128.h"
 
 #include "architecture.h"
-#include "shared-forward.h"
 #include "gpt.h"
+#include "iovec-util.h"
 #include "list.h"
+#include "shared-forward.h"
 
 typedef struct DecryptedImage DecryptedImage;
 
@@ -120,12 +121,10 @@ typedef struct MountOptions {
 
 typedef struct VeritySettings {
         /* Binary root hash for the Verity Merkle tree */
-        void *root_hash;
-        size_t root_hash_size;
+        struct iovec root_hash;
 
         /* PKCS#7 signature of the above */
-        void *root_hash_sig;
-        size_t root_hash_sig_size;
+        struct iovec root_hash_sig;
 
         /* Path to the verity data file, if stored externally */
         char *data_path;
@@ -206,9 +205,9 @@ int verity_settings_load(VeritySettings *verity, const char *image, const char *
 
 static inline bool verity_settings_set(const VeritySettings *settings) {
         return settings &&
-                (settings->root_hash_size > 0 ||
-                 (settings->root_hash_sig_size > 0 ||
-                  settings->data_path));
+                (iovec_is_set(&settings->root_hash) ||
+                 iovec_is_set(&settings->root_hash_sig) ||
+                 settings->data_path);
 }
 
 void verity_settings_done(VeritySettings *verity);
@@ -223,7 +222,7 @@ static inline bool verity_settings_data_covers(const VeritySettings *verity, Par
         /* Returns true if the verity settings contain sufficient information to cover the specified partition */
         return verity &&
                 ((d >= 0 && verity->designator == d) || (d == PARTITION_ROOT && verity->designator < 0)) &&
-                verity->root_hash &&
+                iovec_is_set(&verity->root_hash) &&
                 verity->data_path;
 }
 
index 32aea19a6fb1a065ac8a1129780a7564c66dbcfa..1f3728d2293c085a35b8e902547f8f8af9a92f72 100644 (file)
@@ -74,7 +74,7 @@ static int acquire_verity_settings(VeritySettings *ret) {
         }
 
         if (h) {
-                r = unhexmem(h, &verity.root_hash, &verity.root_hash_size);
+                r = unhexmem(h, &verity.root_hash.iov_base, &verity.root_hash.iov_len);
                 if (r < 0)
                         return log_error_errno(r, "Failed to parse root hash from kernel command line switch: %m");
         }
@@ -301,25 +301,25 @@ static int verb_probe(UdevEvent *event, sd_device *dev) {
                 }
 
                 if (d == verity.designator) {
-                        if (verity.root_hash_size > 0) {
+                        if (iovec_is_set(&verity.root_hash)) {
                                 _cleanup_free_ char *f = NULL;
                                 if (asprintf(&f, "ID_DISSECT_PART%i_ROOTHASH", p->partno) < 0)
                                         return log_oom_debug();
 
-                                _cleanup_free_ char *h = hexmem(verity.root_hash, verity.root_hash_size);
+                                _cleanup_free_ char *h = hexmem(verity.root_hash.iov_base, verity.root_hash.iov_len);
                                 if (!h)
                                         return log_oom_debug();
 
                                 (void) udev_builtin_add_property(event, f, h);
                         }
 
-                        if (verity.root_hash_sig_size > 0) {
+                        if (iovec_is_set(&verity.root_hash_sig)) {
                                 _cleanup_free_ char *f = NULL;
                                 if (asprintf(&f, "ID_DISSECT_PART%i_ROOTHASH_SIG", p->partno) < 0)
                                         return log_oom_debug();
 
                                 _cleanup_free_ char *h = NULL;
-                                if (base64mem(verity.root_hash_sig, verity.root_hash_sig_size, &h) < 0)
+                                if (base64mem(verity.root_hash_sig.iov_base, verity.root_hash_sig.iov_len, &h) < 0)
                                         return log_oom_debug();
 
                                 (void) udev_builtin_add_property(event, f, h);