From 0389f4fa81e93be298721ce699889161fbe4046b Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 3 Jun 2020 09:50:45 +0100 Subject: core: add RootHash and RootVerity service parameters Allow to explicitly pass root hash (explicitly or as a file) and verity device/file as unit options. Take precedence over implicit checks. --- man/systemd.exec.xml | 37 +++++++++++++++ src/core/dbus-execute.c | 71 +++++++++++++++++++++++++++++ src/core/execute.c | 19 ++++++++ src/core/execute.h | 4 +- src/core/load-fragment-gperf.gperf.m4 | 2 + src/core/load-fragment.c | 59 ++++++++++++++++++++++++ src/core/load-fragment.h | 1 + src/core/namespace.c | 16 ++++--- src/core/namespace.h | 4 ++ src/dissect/dissect.c | 2 +- src/nspawn/nspawn.c | 2 +- src/shared/bus-unit-util.c | 21 +++++++++ src/shared/dissect-image.c | 37 +++++++++------ src/shared/dissect-image.h | 2 +- src/test/test-namespace.c | 4 ++ src/test/test-ns.c | 4 ++ test/fuzz/fuzz-unit-file/directives.service | 2 + 17 files changed, 262 insertions(+), 25 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index f5db55511f..aa8a3f75bc 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -145,6 +145,43 @@ + + RootHash= + + 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 RootVerity= 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 user.verity.roothash extended file attribute (see xattr7), 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 .roothash suffix is + found next to the image file, bearing otherwise the same name (except if the image has the + .raw 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. + + + + + + RootVerity= + + Takes the path to a data integrity (dm-verity) file. This option enables data integrity checks + using dm-verity, if RootImage= 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 .verity suffix is found next to the image file, bearing otherwise + the same name (except if the image has the .raw 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. + + 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) + + + + MountAPIVFS= diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 06b6b95d69..a584895ea9 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -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); diff --git a/src/core/execute.c b/src/core/execute.c index aa253a5ddf..e0835f9b92 100644 --- a/src/core/execute.c +++ b/src/core/execute.c @@ -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); diff --git a/src/core/execute.h b/src/core/execute.h index 7e1015631f..7c9d63c5e4 100644 --- a/src/core/execute.h +++ b/src/core/execute.h @@ -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; diff --git a/src/core/load-fragment-gperf.gperf.m4 b/src/core/load-fragment-gperf.gperf.m4 index 69598e8430..9cf959edd5 100644 --- a/src/core/load-fragment-gperf.gperf.m4 +++ b/src/core/load-fragment-gperf.gperf.m4 @@ -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) diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index c1a4eb96cb..54b3514924 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -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, diff --git a/src/core/load-fragment.h b/src/core/load-fragment.h index 9c30b6f882..f0e109da3a 100644 --- a/src/core/load-fragment.h +++ b/src/core/load-fragment.h @@ -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); diff --git a/src/core/namespace.c b/src/core/namespace.c index 6bfc266dc0..423a47c7b8 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -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"); } diff --git a/src/core/namespace.h b/src/core/namespace.h index ef6c9bdc9b..a687be5bfd 100644 --- a/src/core/namespace.h +++ b/src/core/namespace.h @@ -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); diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index 9ae632f226..2a8eaca5bd 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -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); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index f3a3ee8a17..ae6828f2bf 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -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); diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 4b1145a6ba..e539d03149 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -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; } diff --git a/src/shared/dissect-image.c b/src/shared/dissect-image.c index 2c8a5d85bf..e576518c6b 100644 --- a/src/shared/dissect-image.c +++ b/src/shared/dissect-image.c @@ -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) { diff --git a/src/shared/dissect-image.h b/src/shared/dissect-image.h index 92d223cfec..6a53b94948 100644 --- a/src/shared/dissect-image.h +++ b/src/shared/dissect-image.h @@ -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); diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c index f2bfc6c62b..d0b4ec2764 100644 --- a/src/test/test-namespace.c +++ b/src/test/test-namespace.c @@ -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); diff --git a/src/test/test-ns.c b/src/test/test-ns.c index cf8b08ba9b..ba2c2ed53b 100644 --- a/src/test/test-ns.c +++ b/src/test/test-ns.c @@ -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) { diff --git a/test/fuzz/fuzz-unit-file/directives.service b/test/fuzz/fuzz-unit-file/directives.service index 7435d7abec..492d2a033b 100644 --- a/test/fuzz/fuzz-unit-file/directives.service +++ b/test/fuzz/fuzz-unit-file/directives.service @@ -196,6 +196,8 @@ ReusePort= RootDirectory= RootDirectoryStartOnly= RootImage= +RootHash= +RootVerity= RuntimeMaxSec= SELinuxContextFromNet= SecureBits= -- cgit v1.2.1