Add a dedicated ".dm-verity" keyring for root hash signature verification, similar to the ".fs-verity" keyring used by fs-verity.
By default the keyring is unused retaining the exact same old behavior. For systems that provision additional keys only intended for dm-verity images during boot, the dm_verity.keyring_unsealed=1 kernel parameter leaves the keyring open. We want to use this in systemd as a way add keys during boot that are only used for creating dm-verity devices for later mounting and nothing else. The discoverable disk image (DDI) spec at [1] heavily relies on dm-verity and we would like to expand this even more. This will allow us to do that in a fully backward compatible way. Once provisioning is complete, userspace restricts and activates it for dm-verity verification. If userspace fully seals the keyring then it gains the guarantee that no new keys can be added. Link: https://uapi-group.org/specifications/specs/discoverable_partitions_specification [1] Co-developed-by: Aleksa Sarai <[email protected]> Signed-off-by: Aleksa Sarai <[email protected]> Signed-off-by: Christian Brauner <[email protected]> --- Documentation/admin-guide/kernel-parameters.txt | 7 ++++ drivers/md/dm-verity-target.c | 20 ++++++++++- drivers/md/dm-verity-verify-sig.c | 45 +++++++++++++++++++++++++ drivers/md/dm-verity-verify-sig.h | 12 +++++++ 4 files changed, 83 insertions(+), 1 deletion(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index a8d0afde7f85..374571c7921a 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -1370,6 +1370,13 @@ Kernel parameters For details see: Documentation/admin-guide/hw-vuln/reg-file-data-sampling.rst + dm_verity.keyring_unsealed= + [KNL] When set to 1, leave the dm-verity keyring + unsealed after initialization so userspace can + provision keys. Once the keyring is restricted + it becomes active and is searched during signature + verification. + driver_async_probe= [KNL] List of driver names to be probed asynchronously. * matches with all driver names. If * is specified, the diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c index 5c17472d7896..835358f63d09 100644 --- a/drivers/md/dm-verity-target.c +++ b/drivers/md/dm-verity-target.c @@ -1803,7 +1803,25 @@ static struct target_type verity_target = { .preresume = verity_preresume, #endif /* CONFIG_SECURITY */ }; -module_dm(verity); + +static int __init dm_verity_init(void) +{ + int r; + + r = dm_verity_verify_sig_init(); + if (r) + return r; + + return dm_register_target(&verity_target); +} +module_init(dm_verity_init); + +static void __exit dm_verity_exit(void) +{ + dm_unregister_target(&verity_target); + dm_verity_verify_sig_exit(); +} +module_exit(dm_verity_exit); /* * Check whether a DM target is a verity target. diff --git a/drivers/md/dm-verity-verify-sig.c b/drivers/md/dm-verity-verify-sig.c index d5261a0e4232..2a2abd9864c9 100644 --- a/drivers/md/dm-verity-verify-sig.c +++ b/drivers/md/dm-verity-verify-sig.c @@ -7,6 +7,7 @@ */ #include <linux/device-mapper.h> #include <linux/verification.h> +#include <linux/key.h> #include <keys/user-type.h> #include <linux/module.h> #include "dm-verity.h" @@ -14,6 +15,12 @@ #define DM_VERITY_VERIFY_ERR(s) DM_VERITY_ROOT_HASH_VERIFICATION " " s +static struct key *dm_verity_keyring; + +static bool dm_verity_keyring_unsealed __ro_after_init; +module_param_named(keyring_unsealed, dm_verity_keyring_unsealed, bool, 0444); +MODULE_PARM_DESC(keyring_unsealed, "Leave the dm-verity keyring unsealed"); + static bool require_signatures; module_param(require_signatures, bool, 0444); MODULE_PARM_DESC(require_signatures, @@ -143,6 +150,17 @@ int verity_verify_root_hash(const void *root_hash, size_t root_hash_len, VERIFYING_UNSPECIFIED_SIGNATURE, NULL, NULL); #endif + if (ret != -ENOKEY && ret != -EKEYREJECTED) + return ret; + + if (dm_verity_keyring->keys.nr_leaves_on_tree && + dm_verity_keyring->restrict_link) + ret = verify_pkcs7_signature(root_hash, root_hash_len, + sig_data, sig_len, + dm_verity_keyring, + VERIFYING_UNSPECIFIED_SIGNATURE, + NULL, NULL); + return ret; } @@ -152,3 +170,30 @@ void verity_verify_sig_opts_cleanup(struct dm_verity_sig_opts *sig_opts) sig_opts->sig = NULL; sig_opts->sig_size = 0; } + +int __init dm_verity_verify_sig_init(void) +{ + dm_verity_keyring = keyring_alloc(".dm-verity", + GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, + current_cred(), + KEY_POS_SEARCH | + KEY_USR_VIEW | KEY_USR_READ | + KEY_USR_WRITE | KEY_USR_SEARCH | + KEY_USR_SETATTR, + KEY_ALLOC_NOT_IN_QUOTA, + NULL, NULL); + if (IS_ERR(dm_verity_keyring)) + panic("dm-verity can't allocate keyring\n"); + + if (!dm_verity_keyring_unsealed && + keyring_restrict(make_key_ref(dm_verity_keyring, true), NULL, NULL)) + panic("dm-verity can't seal keyring\n"); + + return 0; +} + +void __exit dm_verity_verify_sig_exit(void) +{ + key_revoke(dm_verity_keyring); + key_put(dm_verity_keyring); +} diff --git a/drivers/md/dm-verity-verify-sig.h b/drivers/md/dm-verity-verify-sig.h index f36ea92127bf..b0bb0d427244 100644 --- a/drivers/md/dm-verity-verify-sig.h +++ b/drivers/md/dm-verity-verify-sig.h @@ -30,6 +30,9 @@ int verity_verify_sig_parse_opt_args(struct dm_arg_set *as, struct dm_verity *v, void verity_verify_sig_opts_cleanup(struct dm_verity_sig_opts *sig_opts); +int __init dm_verity_verify_sig_init(void); +void __exit dm_verity_verify_sig_exit(void); + #else #define DM_VERITY_ROOT_HASH_VERIFICATION_OPTS 0 @@ -56,5 +59,14 @@ static inline void verity_verify_sig_opts_cleanup(struct dm_verity_sig_opts *sig { } +static inline int dm_verity_verify_sig_init(void) +{ + return 0; +} + +static inline void dm_verity_verify_sig_exit(void) +{ +} + #endif /* CONFIG_DM_VERITY_VERIFY_ROOTHASH_SIG */ #endif /* DM_VERITY_SIG_VERIFICATION_H */ -- 2.47.3
