]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: add RootHash and RootVerity service parameters
authorLuca Boccassi <luca.boccassi@microsoft.com>
Wed, 3 Jun 2020 08:50:45 +0000 (09:50 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 23 Jun 2020 08:50:09 +0000 (10:50 +0200)
Allow to explicitly pass root hash (explicitly or as a file) and verity
device/file as unit options. Take precedence over implicit checks.

17 files changed:
man/systemd.exec.xml
src/core/dbus-execute.c
src/core/execute.c
src/core/execute.h
src/core/load-fragment-gperf.gperf.m4
src/core/load-fragment.c
src/core/load-fragment.h
src/core/namespace.c
src/core/namespace.h
src/dissect/dissect.c
src/nspawn/nspawn.c
src/shared/bus-unit-util.c
src/shared/dissect-image.c
src/shared/dissect-image.h
src/test/test-namespace.c
src/test/test-ns.c
test/fuzz/fuzz-unit-file/directives.service

index f5db55511fda50d40ee3e55f21eb5c30e5e20da9..aa8a3f75bc547646545bdb5496589f3ea100bc8a 100644 (file)
         <xi:include href="system-only.xml" xpointer="singular"/></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>RootHash=</varname></term>
+
+        <listitem><para>Takes a data integrity (dm-verity) root hash specified in hexadecimal, or the path to a file
+        containing a root hash in ASCII hexadecimal format. This option enables data integrity checks using dm-verity,
+        if the used image contains the appropriate integrity data (see above) or if <varname>RootVerity=</varname> is used.
+        The specified hash must match the root hash of integrity data, and is usually at least 256 bits (and hence 64
+        formatted hexadecimal characters) long (in case of SHA256 for example). If this option is not specified, but
+        the image file carries the <literal>user.verity.roothash</literal> extended file attribute (see <citerefentry
+        project='man-pages'><refentrytitle>xattr</refentrytitle><manvolnum>7</manvolnum></citerefentry>), then the root
+        hash is read from it, also as formatted hexadecimal characters. If the extended file attribute is not found (or
+        is not supported by the underlying file system), but a file with the <filename>.roothash</filename> suffix is
+        found next to the image file, bearing otherwise the same name (except if the image has the
+        <filename>.raw</filename> suffix, in which case the root hash file must not have it in its name), the root hash
+        is read from it and automatically used, also as formatted hexadecimal characters.</para>
+
+        <xi:include href="system-only.xml" xpointer="singular"/></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>RootVerity=</varname></term>
+
+        <listitem><para>Takes the path to a data integrity (dm-verity) file. This option enables data integrity checks
+        using dm-verity, if <varname>RootImage=</varname> is used and a root-hash is passed and if the used image itself
+        does not contains the integrity data. The integrity data must be matched by the root hash. If this option is not
+        specified, but a file with the <filename>.verity</filename> suffix is found next to the image file, bearing otherwise
+        the same name (except if the image has the <filename>.raw</filename> suffix, in which case the verity data file must
+        not have it in its name), the verity data is read from it and automatically used.</para>
+
+        <para>This option is supported only for disk images that contain a single file system, without an enveloping partition
+        table. Images that contain a GPT partition table should instead include both root file system and matching Verity
+        data in the same image, implementing the
+        [Discoverable Partition Specification](https://systemd.io/DISCOVERABLE_PARTITIONS)</para>
+
+        <xi:include href="system-only.xml" xpointer="singular"/></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>MountAPIVFS=</varname></term>
 
index 06b6b95d6962966e1c2b2d4c92966e10cdeb3eb6..a584895ea9ee64ba2c1e4e4eb435ccbf6ea61006 100644 (file)
@@ -746,6 +746,25 @@ static int property_get_log_extra_fields(
         return sd_bus_message_close_container(reply);
 }
 
+static int property_get_root_hash(
+                sd_bus *bus,
+                const char *path,
+                const char *interface,
+                const char *property,
+                sd_bus_message *reply,
+                void *userdata,
+                sd_bus_error *error) {
+
+        ExecContext *c = userdata;
+
+        assert(bus);
+        assert(c);
+        assert(property);
+        assert(reply);
+
+        return sd_bus_message_append_array(reply, 'y', c->root_hash, c->root_hash_size);
+}
+
 const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_VTABLE_START(0),
         SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -788,6 +807,9 @@ const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("RootImage", "s", NULL, offsetof(ExecContext, root_image), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("RootHash", "ay", property_get_root_hash, 0, SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("RootHashPath", "s", NULL, offsetof(ExecContext, root_hash_path), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("RootVerity", "s", NULL, offsetof(ExecContext, root_verity), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("CoredumpFilter", "t", property_get_coredump_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
@@ -1258,6 +1280,55 @@ int bus_exec_context_set_transient_property(
         if (streq(name, "RootImage"))
                 return bus_set_transient_path(u, name, &c->root_image, message, flags, error);
 
+        if (streq(name, "RootHash")) {
+                const void *roothash_decoded;
+                size_t roothash_decoded_size;
+
+                r = sd_bus_message_read_array(message, 'y', &roothash_decoded, &roothash_decoded_size);
+                if (r < 0)
+                        return r;
+
+                if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
+                        _cleanup_free_ char *encoded = NULL;
+
+                        if (roothash_decoded_size == 0) {
+                                c->root_hash_path = mfree(c->root_hash_path);
+                                c->root_hash = mfree(c->root_hash);
+                                c->root_hash_size = 0;
+
+                                unit_write_settingf(u, flags, name, "RootHash=");
+                        } else {
+                                _cleanup_free_ void *p;
+
+                                encoded = hexmem(roothash_decoded, roothash_decoded_size);
+                                if (!encoded)
+                                        return -ENOMEM;
+
+                                p = memdup(roothash_decoded, roothash_decoded_size);
+                                if (!p)
+                                        return -ENOMEM;
+
+                                free_and_replace(c->root_hash, p);
+                                c->root_hash_size = roothash_decoded_size;
+                                c->root_hash_path = mfree(c->root_hash_path);
+
+                                unit_write_settingf(u, flags, name, "RootHash=%s", encoded);
+                        }
+                }
+
+                return 1;
+        }
+
+        if (streq(name, "RootHashPath")) {
+                c->root_hash_size = 0;
+                c->root_hash = mfree(c->root_hash);
+
+                return bus_set_transient_path(u, "RootHash", &c->root_hash_path, message, flags, error);
+        }
+
+        if (streq(name, "RootVerity"))
+                return bus_set_transient_path(u, name, &c->root_verity, message, flags, error);
+
         if (streq(name, "RootDirectory"))
                 return bus_set_transient_path(u, name, &c->root_directory, message, flags, error);
 
index aa253a5ddff0aaebf059c75bf3b5c13c6c9c954f..e0835f9b92ca778ad1f86e4861bfac5ae645badb 100644 (file)
@@ -54,6 +54,7 @@
 #include "format-util.h"
 #include "fs-util.h"
 #include "glob-util.h"
+#include "hexdecoct.h"
 #include "io-util.h"
 #include "ioprio.h"
 #include "label.h"
@@ -2666,6 +2667,7 @@ static int apply_mount_namespace(
                             needs_sandboxing ? context->protect_home : PROTECT_HOME_NO,
                             needs_sandboxing ? context->protect_system : PROTECT_SYSTEM_NO,
                             context->mount_flags,
+                            context->root_hash, context->root_hash_size, context->root_hash_path, context->root_verity,
                             DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK,
                             error_path);
 
@@ -4195,6 +4197,10 @@ void exec_context_done(ExecContext *c) {
         c->working_directory = mfree(c->working_directory);
         c->root_directory = mfree(c->root_directory);
         c->root_image = mfree(c->root_image);
+        c->root_hash = mfree(c->root_hash);
+        c->root_hash_size = 0;
+        c->root_hash_path = mfree(c->root_hash_path);
+        c->root_verity = mfree(c->root_verity);
         c->tty_path = mfree(c->tty_path);
         c->syslog_identifier = mfree(c->syslog_identifier);
         c->user = mfree(c->user);
@@ -4599,6 +4605,19 @@ void exec_context_dump(const ExecContext *c, FILE* f, const char *prefix) {
         if (c->root_image)
                 fprintf(f, "%sRootImage: %s\n", prefix, c->root_image);
 
+        if (c->root_hash) {
+                _cleanup_free_ char *encoded = NULL;
+                encoded = hexmem(c->root_hash, c->root_hash_size);
+                if (encoded)
+                        fprintf(f, "%sRootHash: %s\n", prefix, encoded);
+        }
+
+        if (c->root_hash_path)
+                fprintf(f, "%sRootHash: %s\n", prefix, c->root_hash_path);
+
+        if (c->root_verity)
+                fprintf(f, "%sRootVerity: %s\n", prefix, c->root_verity);
+
         STRV_FOREACH(e, c->environment)
                 fprintf(f, "%sEnvironment: %s\n", prefix, *e);
 
index 7e1015631f1ffe35748b82f987fab66edae602b7..7c9d63c5e414b51b399451326524e9a0950807d4 100644 (file)
@@ -155,7 +155,9 @@ struct ExecContext {
         char **unset_environment;
 
         struct rlimit *rlimit[_RLIMIT_MAX];
-        char *working_directory, *root_directory, *root_image;
+        char *working_directory, *root_directory, *root_image, *root_verity, *root_hash_path;
+        void *root_hash;
+        size_t root_hash_size;
         bool working_directory_missing_ok:1;
         bool working_directory_home:1;
 
index 69598e8430c1a00906ea003458eb61d7988527dc..9cf959edd57432fb603c35e6ce7f2da14ee8e76c 100644 (file)
@@ -23,6 +23,8 @@ m4_define(`EXEC_CONTEXT_CONFIG_ITEMS',
 `$1.WorkingDirectory,            config_parse_working_directory,     0,                             offsetof($1, exec_context)
 $1.RootDirectory,                config_parse_unit_path_printf,      true,                          offsetof($1, exec_context.root_directory)
 $1.RootImage,                    config_parse_unit_path_printf,      true,                          offsetof($1, exec_context.root_image)
+$1.RootHash,                     config_parse_exec_root_hash,        0,                             offsetof($1, exec_context)
+$1.RootVerity,                   config_parse_unit_path_printf,      true,                          offsetof($1, exec_context.root_verity)
 $1.User,                         config_parse_user_group_compat,     0,                             offsetof($1, exec_context.user)
 $1.Group,                        config_parse_user_group_compat,     0,                             offsetof($1, exec_context.group)
 $1.SupplementaryGroups,          config_parse_user_group_strv_compat, 0,                            offsetof($1, exec_context.supplementary_groups)
index c1a4eb96cb884b3f4b8b2d389fd319fb4cc2edd3..54b35149244384e4105fce973beebbfc8edffdd9 100644 (file)
@@ -29,6 +29,7 @@
 #include "errno-list.h"
 #include "escape.h"
 #include "fd-util.h"
+#include "fileio.h"
 #include "fs-util.h"
 #include "hexdecoct.h"
 #include "io-util.h"
@@ -1413,6 +1414,64 @@ int config_parse_exec_cpu_sched_prio(const char *unit,
         return 0;
 }
 
+int config_parse_exec_root_hash(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        _cleanup_free_ void *roothash_decoded = NULL;
+        ExecContext *c = data;
+        size_t roothash_decoded_size = 0;
+        int r;
+
+        assert(data);
+        assert(filename);
+        assert(line);
+        assert(rvalue);
+
+        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;
+                return 0;
+        }
+
+        if (path_is_absolute(rvalue)) {
+                /* We have the path to a roothash to load and decode, eg: RootHash=/foo/bar.roothash */
+                _cleanup_free_ char *p = NULL;
+
+                p = strdup(rvalue);
+                if (!p)
+                        return -ENOMEM;
+
+                free_and_replace(c->root_hash_path, p);
+                c->root_hash = mfree(c->root_hash);
+                c->root_hash_size = 0;
+                return 0;
+        }
+
+        /* We have a roothash to decode, eg: RootHash=012345789abcdef */
+        r = unhexmem(rvalue, strlen(rvalue), &roothash_decoded, &roothash_decoded_size);
+        if (r < 0)
+                return log_syntax(unit, LOG_ERR, filename, line, r, "Failed to decode RootHash=, ignoring: %s", rvalue);
+        if (roothash_decoded_size < sizeof(sd_id128_t))
+                return log_syntax(unit, LOG_ERR, filename, line, SYNTHETIC_ERRNO(EINVAL), "RootHash= is too short, ignoring: %s", rvalue);
+
+        free_and_replace(c->root_hash, roothash_decoded);
+        c->root_hash_size = roothash_decoded_size;
+        c->root_hash_path = mfree(c->root_hash_path);
+
+        return 0;
+}
+
 int config_parse_exec_cpu_affinity(const char *unit,
                                    const char *filename,
                                    unsigned line,
index 9c30b6f882b30fb85672c93160d8a9a04b61baf7..f0e109da3ac3f729a151d0aa03539b7f83760b52 100644 (file)
@@ -44,6 +44,7 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_policy);
 CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_sched_prio);
 CONFIG_PARSER_PROTOTYPE(config_parse_exec_cpu_affinity);
 CONFIG_PARSER_PROTOTYPE(config_parse_exec_secure_bits);
+CONFIG_PARSER_PROTOTYPE(config_parse_exec_root_hash);
 CONFIG_PARSER_PROTOTYPE(config_parse_capability_set);
 CONFIG_PARSER_PROTOTYPE(config_parse_exec_mount_flags);
 CONFIG_PARSER_PROTOTYPE(config_parse_timer);
index 6bfc266dc00f57cc4e80b739dad7e0b4bdb0145f..423a47c7b8ce855c81c1ea6f099ea505cc476100 100644 (file)
@@ -1257,16 +1257,20 @@ int setup_namespace(
                 ProtectHome protect_home,
                 ProtectSystem protect_system,
                 unsigned long mount_flags,
+                const void *root_hash,
+                size_t root_hash_size,
+                const char *root_hash_path,
+                const char *root_verity,
                 DissectImageFlags dissect_image_flags,
                 char **error_path) {
 
         _cleanup_(loop_device_unrefp) LoopDevice *loop_device = NULL;
         _cleanup_(decrypted_image_unrefp) DecryptedImage *decrypted_image = NULL;
         _cleanup_(dissected_image_unrefp) DissectedImage *dissected_image = NULL;
-        _cleanup_free_ void *root_hash = NULL;
+        _cleanup_free_ void *root_hash_decoded = NULL;
         _cleanup_free_ char *verity_data = NULL;
         MountEntry *m = NULL, *mounts = NULL;
-        size_t n_mounts, root_hash_size = 0;
+        size_t n_mounts;
         bool require_prefix = false;
         const char *root;
         int r = 0;
@@ -1295,16 +1299,16 @@ int setup_namespace(
                 if (r < 0)
                         return log_debug_errno(r, "Failed to create loop device for root image: %m");
 
-                r = verity_metadata_load(root_image, &root_hash, &root_hash_size, &verity_data);
+                r = verity_metadata_load(root_image, root_hash_path, root_hash ? NULL : &root_hash_decoded, root_hash ? NULL : &root_hash_size, root_verity ? NULL : &verity_data);
                 if (r < 0)
                         return log_debug_errno(r, "Failed to load root hash: %m");
-                dissect_image_flags |= verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
+                dissect_image_flags |= root_verity || verity_data ? DISSECT_IMAGE_NO_PARTITION_TABLE : 0;
 
-                r = dissect_image(loop_device->fd, root_hash, root_hash_size, verity_data, dissect_image_flags, &dissected_image);
+                r = dissect_image(loop_device->fd, root_hash ?: root_hash_decoded, root_hash_size, root_verity ?: verity_data, dissect_image_flags, &dissected_image);
                 if (r < 0)
                         return log_debug_errno(r, "Failed to dissect image: %m");
 
-                r = dissected_image_decrypt(dissected_image, NULL, root_hash, root_hash_size, verity_data, dissect_image_flags, &decrypted_image);
+                r = dissected_image_decrypt(dissected_image, NULL, root_hash ?: root_hash_decoded, root_hash_size, root_verity ?: verity_data, dissect_image_flags, &decrypted_image);
                 if (r < 0)
                         return log_debug_errno(r, "Failed to decrypt dissected image: %m");
         }
index ef6c9bdc9bdcaa8bb3c68b93ff4e6ee42164d1ef..a687be5bfda92776dfefbf67690c5cf46f0a778d 100644 (file)
@@ -88,6 +88,10 @@ int setup_namespace(
                 ProtectHome protect_home,
                 ProtectSystem protect_system,
                 unsigned long mount_flags,
+                const void *root_hash,
+                size_t root_hash_size,
+                const char *root_hash_path,
+                const char *root_verity,
                 DissectImageFlags dissected_image_flags,
                 char **error_path);
 
index 9ae632f226700fa62bfcbcbd2b23d9abed3b3f96..2a8eaca5bd10945de87700b4792ccbb8791c28fa 100644 (file)
@@ -201,7 +201,7 @@ static int run(int argc, char *argv[]) {
         if (r < 0)
                 return log_error_errno(r, "Failed to set up loopback device: %m");
 
-        r = verity_metadata_load(arg_image, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
+        r = verity_metadata_load(arg_image, NULL, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
                            arg_verity_data ? NULL : &arg_verity_data);
         if (r < 0)
                 return log_error_errno(r, "Failed to read verity artefacts for %s: %m", arg_image);
index f3a3ee8a171e9d848dd5059baba8120380fabc98..ae6828f2bf29e04229b3137d5b1a37a5f8a5bc24 100644 (file)
@@ -5141,7 +5141,7 @@ static int run(int argc, char *argv[]) {
                                 goto finish;
                         }
 
-                        r = verity_metadata_load(arg_image, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
+                        r = verity_metadata_load(arg_image, NULL, arg_root_hash ? NULL : &arg_root_hash, &arg_root_hash_size,
                                         arg_verity_data ? NULL : &arg_verity_data);
                         if (r < 0) {
                                 log_error_errno(r, "Failed to read verity artefacts for %s: %m", arg_image);
index 4b1145a6ba3cc29d869e10ded3369b0703fa94e4..e539d031495741b8998016a26de7727cfc19c78f 100644 (file)
@@ -13,6 +13,7 @@
 #include "escape.h"
 #include "exec-util.h"
 #include "exit-status.h"
+#include "fileio.h"
 #include "hexdecoct.h"
 #include "hostname-util.h"
 #include "in-addr-util.h"
@@ -24,6 +25,7 @@
 #include "nsflags.h"
 #include "numa-util.h"
 #include "parse-util.h"
+#include "path-util.h"
 #include "process-util.h"
 #include "rlimit-util.h"
 #include "securebits-util.h"
@@ -849,6 +851,7 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
                               "ProtectHome",
                               "SELinuxContext",
                               "RootImage",
+                              "RootVerity",
                               "RuntimeDirectoryPreserve",
                               "Personality",
                               "KeyringMode",
@@ -1415,6 +1418,24 @@ static int bus_append_execute_property(sd_bus_message *m, const char *field, con
                 return 1;
         }
 
+        if (streq(field, "RootHash")) {
+                _cleanup_free_ void *roothash_decoded = NULL;
+                size_t roothash_decoded_size = 0;
+
+                /* We have the path to a roothash to load and decode, eg: RootHash=/foo/bar.roothash */
+                if (path_is_absolute(eq))
+                        return bus_append_string(m, "RootHashPath", eq);
+
+                /* We have a roothash to decode, eg: RootHash=012345789abcdef */
+                r = unhexmem(eq, strlen(eq), &roothash_decoded, &roothash_decoded_size);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to decode RootHash= '%s': %m", eq);
+                if (roothash_decoded_size < sizeof(sd_id128_t))
+                        return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "RootHash= '%s' is too short: %m", eq);
+
+                return bus_append_byte_array(m, field, roothash_decoded, roothash_decoded_size);
+        }
+
         return 0;
 }
 
index 2c8a5d85bfec01ff228060ccabd08d490cc639b5..e576518c6b8e4aa5c566aad3df5d5e187b3fa679 100644 (file)
@@ -1421,7 +1421,7 @@ int decrypted_image_relinquish(DecryptedImage *d) {
         return 0;
 }
 
-int verity_metadata_load(const char *image, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data) {
+int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data) {
         _cleanup_free_ char *verity_filename = NULL;
         _cleanup_free_ void *roothash_decoded = NULL;
         size_t roothash_decoded_size = 0;
@@ -1465,24 +1465,31 @@ int verity_metadata_load(const char *image, void **ret_roothash, size_t *ret_roo
                 _cleanup_free_ char *text = NULL;
                 assert(ret_roothash_size);
 
-                r = getxattr_malloc(image, "user.verity.roothash", &text, true);
-                if (r < 0) {
-                        char *fn, *e, *n;
-
-                        if (!IN_SET(r, -ENODATA, -EOPNOTSUPP, -ENOENT))
+                if (root_hash_path) {
+                        /* We have the path to a roothash to load and decode, eg: RootHash=/foo/bar.roothash */
+                        r = read_one_line_file(root_hash_path, &text);
+                        if (r < 0)
                                 return r;
+                } else {
+                        r = getxattr_malloc(image, "user.verity.roothash", &text, true);
+                        if (r < 0) {
+                                char *fn, *e, *n;
+
+                                if (!IN_SET(r, -ENODATA, -EOPNOTSUPP, -ENOENT))
+                                        return r;
 
-                        fn = newa(char, strlen(image) + STRLEN(".roothash") + 1);
-                        n = stpcpy(fn, image);
-                        e = endswith(fn, ".raw");
-                        if (e)
-                                n = e;
+                                fn = newa(char, strlen(image) + STRLEN(".roothash") + 1);
+                                n = stpcpy(fn, image);
+                                e = endswith(fn, ".raw");
+                                if (e)
+                                        n = e;
 
-                        strcpy(n, ".roothash");
+                                strcpy(n, ".roothash");
 
-                        r = read_one_line_file(fn, &text);
-                        if (r < 0 && r != -ENOENT)
-                                return r;
+                                r = read_one_line_file(fn, &text);
+                                if (r < 0 && r != -ENOENT)
+                                        return r;
+                        }
                 }
 
                 if (text) {
index 92d223cfec5708a4a3e811512d92dbf22b397ff6..6a53b949486fb52ee55f3004d969745da97bc592 100644 (file)
@@ -100,6 +100,6 @@ int decrypted_image_relinquish(DecryptedImage *d);
 const char* partition_designator_to_string(int i) _const_;
 int partition_designator_from_string(const char *name) _pure_;
 
-int verity_metadata_load(const char *image, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data);
+int verity_metadata_load(const char *image, const char *root_hash_path, void **ret_roothash, size_t *ret_roothash_size, char **ret_verity_data);
 bool dissected_image_can_do_verity(const DissectedImage *image, unsigned partition_designator);
 bool dissected_image_has_verity(const DissectedImage *image, unsigned partition_designator);
index f2bfc6c62bc9c3f5724e725549cb2932a1bee767..d0b4ec27644710d161cacc2d85e4742944c878f2 100644 (file)
@@ -152,6 +152,10 @@ static void test_protect_kernel_logs(void) {
                                     PROTECT_HOME_NO,
                                     PROTECT_SYSTEM_NO,
                                     0,
+                                    NULL,
+                                    0,
+                                    NULL,
+                                    NULL,
                                     0,
                                     NULL);
                 assert_se(r == 0);
index cf8b08ba9be55dd5dbbf2c255514e0c622beebc7..ba2c2ed53b77b40c4431707b7136344af6d23b99 100644 (file)
@@ -76,6 +76,10 @@ int main(int argc, char *argv[]) {
                             PROTECT_HOME_NO,
                             PROTECT_SYSTEM_NO,
                             0,
+                            NULL,
+                            0,
+                            NULL,
+                            NULL,
                             0,
                             NULL);
         if (r < 0) {
index 7435d7abec0ee1ba7ae406ec3da6f5fbb6f65c8a..492d2a033bb3d078cddb92ea065649b0969372a4 100644 (file)
@@ -196,6 +196,8 @@ ReusePort=
 RootDirectory=
 RootDirectoryStartOnly=
 RootImage=
+RootHash=
+RootVerity=
 RuntimeMaxSec=
 SELinuxContextFromNet=
 SecureBits=