Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ipe: add support for dm-verity as a trust provider

Allows author of IPE policy to indicate trust for a singular dm-verity
volume, identified by roothash, through "dmverity_roothash" and all
signed and validated dm-verity volumes, through "dmverity_signature".

Signed-off-by: Deven Bowers <deven.desai@linux.microsoft.com>
Signed-off-by: Fan Wu <wufan@linux.microsoft.com>
[PM: fixed some line length issues in the comments]
Signed-off-by: Paul Moore <paul@paul-moore.com>

authored by

Deven Bowers and committed by
Paul Moore
e155858d a6af7bc3

+460 -15
+27
security/ipe/Kconfig
··· 8 8 depends on SECURITY && SECURITYFS && AUDIT && AUDITSYSCALL 9 9 select PKCS7_MESSAGE_PARSER 10 10 select SYSTEM_DATA_VERIFICATION 11 + select IPE_PROP_DM_VERITY if DM_VERITY 12 + select IPE_PROP_DM_VERITY_SIGNATURE if DM_VERITY && DM_VERITY_VERIFY_ROOTHASH_SIG 11 13 help 12 14 This option enables the Integrity Policy Enforcement LSM 13 15 allowing users to define a policy to enforce a trust-based access ··· 17 15 admins to reconfigure trust requirements on the fly. 18 16 19 17 If unsure, answer N. 18 + 19 + if SECURITY_IPE 20 + menu "IPE Trust Providers" 21 + 22 + config IPE_PROP_DM_VERITY 23 + bool "Enable support for dm-verity based on root hash" 24 + depends on DM_VERITY 25 + help 26 + This option enables the 'dmverity_roothash' property within IPE 27 + policies. The property evaluates to TRUE when a file from a dm-verity 28 + volume is evaluated, and the volume's root hash matches the value 29 + supplied in the policy. 30 + 31 + config IPE_PROP_DM_VERITY_SIGNATURE 32 + bool "Enable support for dm-verity based on root hash signature" 33 + depends on DM_VERITY && DM_VERITY_VERIFY_ROOTHASH_SIG 34 + help 35 + This option enables the 'dmverity_signature' property within IPE 36 + policies. The property evaluates to TRUE when a file from a dm-verity 37 + volume, which has been mounted with a valid signed root hash, 38 + is evaluated. 39 + 40 + endmenu 41 + 42 + endif
+1
security/ipe/Makefile
··· 6 6 # 7 7 8 8 obj-$(CONFIG_SECURITY_IPE) += \ 9 + digest.o \ 9 10 eval.o \ 10 11 hooks.o \ 11 12 fs.o \
+27 -2
security/ipe/audit.c
··· 13 13 #include "hooks.h" 14 14 #include "policy.h" 15 15 #include "audit.h" 16 + #include "digest.h" 16 17 17 18 #define ACTSTR(x) ((x) == IPE_ACTION_ALLOW ? "ALLOW" : "DENY") 18 19 ··· 53 52 static const char *const audit_prop_names[__IPE_PROP_MAX] = { 54 53 "boot_verified=FALSE", 55 54 "boot_verified=TRUE", 55 + "dmverity_roothash=", 56 + "dmverity_signature=FALSE", 57 + "dmverity_signature=TRUE", 56 58 }; 59 + 60 + /** 61 + * audit_dmv_roothash() - audit the roothash of a dmverity_roothash property. 62 + * @ab: Supplies a pointer to the audit_buffer to append to. 63 + * @rh: Supplies a pointer to the digest structure. 64 + */ 65 + static void audit_dmv_roothash(struct audit_buffer *ab, const void *rh) 66 + { 67 + audit_log_format(ab, "%s", audit_prop_names[IPE_PROP_DMV_ROOTHASH]); 68 + ipe_digest_audit(ab, rh); 69 + } 57 70 58 71 /** 59 72 * audit_rule() - audit an IPE policy rule. ··· 80 65 81 66 audit_log_format(ab, " rule=\"op=%s ", audit_op_names[r->op]); 82 67 83 - list_for_each_entry(ptr, &r->props, next) 84 - audit_log_format(ab, "%s ", audit_prop_names[ptr->type]); 68 + list_for_each_entry(ptr, &r->props, next) { 69 + switch (ptr->type) { 70 + case IPE_PROP_DMV_ROOTHASH: 71 + audit_dmv_roothash(ab, ptr->value); 72 + break; 73 + default: 74 + audit_log_format(ab, "%s", audit_prop_names[ptr->type]); 75 + break; 76 + } 77 + 78 + audit_log_format(ab, " "); 79 + } 85 80 86 81 audit_log_format(ab, "action=%s\"", ACTSTR(r->action)); 87 82 }
+118
security/ipe/digest.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* 3 + * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved. 4 + */ 5 + 6 + #include "digest.h" 7 + 8 + /** 9 + * ipe_digest_parse() - parse a digest in IPE's policy. 10 + * @valstr: Supplies the string parsed from the policy. 11 + * 12 + * Digests in IPE are defined in a standard way: 13 + * <alg_name>:<hex> 14 + * 15 + * Use this function to create a property to parse the digest 16 + * consistently. The parsed digest will be saved in @value in IPE's 17 + * policy. 18 + * 19 + * Return: The parsed digest_info structure on success. If an error occurs, 20 + * the function will return the error value (via ERR_PTR). 21 + */ 22 + struct digest_info *ipe_digest_parse(const char *valstr) 23 + { 24 + struct digest_info *info = NULL; 25 + char *sep, *raw_digest; 26 + size_t raw_digest_len; 27 + u8 *digest = NULL; 28 + char *alg = NULL; 29 + int rc = 0; 30 + 31 + info = kzalloc(sizeof(*info), GFP_KERNEL); 32 + if (!info) 33 + return ERR_PTR(-ENOMEM); 34 + 35 + sep = strchr(valstr, ':'); 36 + if (!sep) { 37 + rc = -EBADMSG; 38 + goto err; 39 + } 40 + 41 + alg = kstrndup(valstr, sep - valstr, GFP_KERNEL); 42 + if (!alg) { 43 + rc = -ENOMEM; 44 + goto err; 45 + } 46 + 47 + raw_digest = sep + 1; 48 + raw_digest_len = strlen(raw_digest); 49 + 50 + info->digest_len = (raw_digest_len + 1) / 2; 51 + digest = kzalloc(info->digest_len, GFP_KERNEL); 52 + if (!digest) { 53 + rc = -ENOMEM; 54 + goto err; 55 + } 56 + 57 + rc = hex2bin(digest, raw_digest, info->digest_len); 58 + if (rc < 0) { 59 + rc = -EINVAL; 60 + goto err; 61 + } 62 + 63 + info->alg = alg; 64 + info->digest = digest; 65 + return info; 66 + 67 + err: 68 + kfree(alg); 69 + kfree(digest); 70 + kfree(info); 71 + return ERR_PTR(rc); 72 + } 73 + 74 + /** 75 + * ipe_digest_eval() - evaluate an IPE digest against another digest. 76 + * @expected: Supplies the policy-provided digest value. 77 + * @digest: Supplies the digest to compare against the policy digest value. 78 + * 79 + * Return: 80 + * * %true - digests match 81 + * * %false - digests do not match 82 + */ 83 + bool ipe_digest_eval(const struct digest_info *expected, 84 + const struct digest_info *digest) 85 + { 86 + return (expected->digest_len == digest->digest_len) && 87 + (!strcmp(expected->alg, digest->alg)) && 88 + (!memcmp(expected->digest, digest->digest, expected->digest_len)); 89 + } 90 + 91 + /** 92 + * ipe_digest_free() - free an IPE digest. 93 + * @info: Supplies a pointer the policy-provided digest to free. 94 + */ 95 + void ipe_digest_free(struct digest_info *info) 96 + { 97 + if (IS_ERR_OR_NULL(info)) 98 + return; 99 + 100 + kfree(info->alg); 101 + kfree(info->digest); 102 + kfree(info); 103 + } 104 + 105 + /** 106 + * ipe_digest_audit() - audit a digest that was sourced from IPE's policy. 107 + * @ab: Supplies the audit_buffer to append the formatted result. 108 + * @info: Supplies a pointer to source the audit record from. 109 + * 110 + * Digests in IPE are audited in this format: 111 + * <alg_name>:<hex> 112 + */ 113 + void ipe_digest_audit(struct audit_buffer *ab, const struct digest_info *info) 114 + { 115 + audit_log_untrustedstring(ab, info->alg); 116 + audit_log_format(ab, ":"); 117 + audit_log_n_hex(ab, info->digest, info->digest_len); 118 + }
+26
security/ipe/digest.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0 */ 2 + /* 3 + * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved. 4 + */ 5 + 6 + #ifndef _IPE_DIGEST_H 7 + #define _IPE_DIGEST_H 8 + 9 + #include <linux/types.h> 10 + #include <linux/audit.h> 11 + 12 + #include "policy.h" 13 + 14 + struct digest_info { 15 + const char *alg; 16 + const u8 *digest; 17 + size_t digest_len; 18 + }; 19 + 20 + struct digest_info *ipe_digest_parse(const char *valstr); 21 + void ipe_digest_free(struct digest_info *digest_info); 22 + void ipe_digest_audit(struct audit_buffer *ab, const struct digest_info *val); 23 + bool ipe_digest_eval(const struct digest_info *expected, 24 + const struct digest_info *digest); 25 + 26 + #endif /* _IPE_DIGEST_H */
+92 -1
security/ipe/eval.c
··· 15 15 #include "eval.h" 16 16 #include "policy.h" 17 17 #include "audit.h" 18 + #include "digest.h" 18 19 19 20 struct ipe_policy __rcu *ipe_active_policy; 20 21 bool success_audit; 21 22 bool enforce = true; 23 + #define INO_BLOCK_DEV(ino) ((ino)->i_sb->s_bdev) 22 24 23 25 #define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb) 24 26 ··· 33 31 { 34 32 ctx->initramfs = ipe_sb(FILE_SUPERBLOCK(file))->initramfs; 35 33 } 34 + 35 + #ifdef CONFIG_IPE_PROP_DM_VERITY 36 + /** 37 + * build_ipe_bdev_ctx() - Build ipe_bdev field of an evaluation context. 38 + * @ctx: Supplies a pointer to the context to be populated. 39 + * @ino: Supplies the inode struct of the file triggered IPE event. 40 + */ 41 + static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino) 42 + { 43 + if (INO_BLOCK_DEV(ino)) 44 + ctx->ipe_bdev = ipe_bdev(INO_BLOCK_DEV(ino)); 45 + } 46 + #else 47 + static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino) 48 + { 49 + } 50 + #endif /* CONFIG_IPE_PROP_DM_VERITY */ 36 51 37 52 /** 38 53 * ipe_build_eval_ctx() - Build an ipe evaluation context. ··· 67 48 ctx->op = op; 68 49 ctx->hook = hook; 69 50 70 - if (file) 51 + if (file) { 71 52 build_ipe_sb_ctx(ctx, file); 53 + build_ipe_bdev_ctx(ctx, d_real_inode(file->f_path.dentry)); 54 + } 72 55 } 73 56 74 57 /** ··· 85 64 { 86 65 return ctx->initramfs; 87 66 } 67 + 68 + #ifdef CONFIG_IPE_PROP_DM_VERITY 69 + /** 70 + * evaluate_dmv_roothash() - Evaluate @ctx against a dmv roothash property. 71 + * @ctx: Supplies a pointer to the context being evaluated. 72 + * @p: Supplies a pointer to the property being evaluated. 73 + * 74 + * Return: 75 + * * %true - The current @ctx match the @p 76 + * * %false - The current @ctx doesn't match the @p 77 + */ 78 + static bool evaluate_dmv_roothash(const struct ipe_eval_ctx *const ctx, 79 + struct ipe_prop *p) 80 + { 81 + return !!ctx->ipe_bdev && 82 + !!ctx->ipe_bdev->root_hash && 83 + ipe_digest_eval(p->value, 84 + ctx->ipe_bdev->root_hash); 85 + } 86 + #else 87 + static bool evaluate_dmv_roothash(const struct ipe_eval_ctx *const ctx, 88 + struct ipe_prop *p) 89 + { 90 + return false; 91 + } 92 + #endif /* CONFIG_IPE_PROP_DM_VERITY */ 93 + 94 + #ifdef CONFIG_IPE_PROP_DM_VERITY_SIGNATURE 95 + /** 96 + * evaluate_dmv_sig_false() - Evaluate @ctx against a dmv sig false property. 97 + * @ctx: Supplies a pointer to the context being evaluated. 98 + * 99 + * Return: 100 + * * %true - The current @ctx match the property 101 + * * %false - The current @ctx doesn't match the property 102 + */ 103 + static bool evaluate_dmv_sig_false(const struct ipe_eval_ctx *const ctx) 104 + { 105 + return !ctx->ipe_bdev || (!ctx->ipe_bdev->dm_verity_signed); 106 + } 107 + 108 + /** 109 + * evaluate_dmv_sig_true() - Evaluate @ctx against a dmv sig true property. 110 + * @ctx: Supplies a pointer to the context being evaluated. 111 + * 112 + * Return: 113 + * * %true - The current @ctx match the property 114 + * * %false - The current @ctx doesn't match the property 115 + */ 116 + static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx *const ctx) 117 + { 118 + return !evaluate_dmv_sig_false(ctx); 119 + } 120 + #else 121 + static bool evaluate_dmv_sig_false(const struct ipe_eval_ctx *const ctx) 122 + { 123 + return false; 124 + } 125 + 126 + static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx *const ctx) 127 + { 128 + return false; 129 + } 130 + #endif /* CONFIG_IPE_PROP_DM_VERITY_SIGNATURE */ 88 131 89 132 /** 90 133 * evaluate_property() - Analyze @ctx against a rule property. ··· 170 85 return !evaluate_boot_verified(ctx); 171 86 case IPE_PROP_BOOT_VERIFIED_TRUE: 172 87 return evaluate_boot_verified(ctx); 88 + case IPE_PROP_DMV_ROOTHASH: 89 + return evaluate_dmv_roothash(ctx, p); 90 + case IPE_PROP_DMV_SIG_FALSE: 91 + return evaluate_dmv_sig_false(ctx); 92 + case IPE_PROP_DMV_SIG_TRUE: 93 + return evaluate_dmv_sig_true(ctx); 173 94 default: 174 95 return false; 175 96 }
+12
security/ipe/eval.h
··· 22 22 bool initramfs; 23 23 }; 24 24 25 + #ifdef CONFIG_IPE_PROP_DM_VERITY 26 + struct ipe_bdev { 27 + #ifdef CONFIG_IPE_PROP_DM_VERITY_SIGNATURE 28 + bool dm_verity_signed; 29 + #endif /* CONFIG_IPE_PROP_DM_VERITY_SIGNATURE */ 30 + struct digest_info *root_hash; 31 + }; 32 + #endif /* CONFIG_IPE_PROP_DM_VERITY */ 33 + 25 34 struct ipe_eval_ctx { 26 35 enum ipe_op_type op; 27 36 enum ipe_hook_type hook; 28 37 29 38 const struct file *file; 30 39 bool initramfs; 40 + #ifdef CONFIG_IPE_PROP_DM_VERITY 41 + const struct ipe_bdev *ipe_bdev; 42 + #endif /* CONFIG_IPE_PROP_DM_VERITY */ 31 43 }; 32 44 33 45 enum ipe_match {
+92
security/ipe/hooks.c
··· 8 8 #include <linux/types.h> 9 9 #include <linux/binfmts.h> 10 10 #include <linux/mman.h> 11 + #include <linux/blk_types.h> 11 12 12 13 #include "ipe.h" 13 14 #include "hooks.h" 14 15 #include "eval.h" 16 + #include "digest.h" 15 17 16 18 /** 17 19 * ipe_bprm_check_security() - ipe security hook function for bprm check. ··· 193 191 { 194 192 ipe_sb(current->fs->root.mnt->mnt_sb)->initramfs = true; 195 193 } 194 + 195 + #ifdef CONFIG_IPE_PROP_DM_VERITY 196 + /** 197 + * ipe_bdev_free_security() - Free IPE's LSM blob of block_devices. 198 + * @bdev: Supplies a pointer to a block_device that contains the structure 199 + * to free. 200 + */ 201 + void ipe_bdev_free_security(struct block_device *bdev) 202 + { 203 + struct ipe_bdev *blob = ipe_bdev(bdev); 204 + 205 + ipe_digest_free(blob->root_hash); 206 + } 207 + 208 + #ifdef CONFIG_IPE_PROP_DM_VERITY_SIGNATURE 209 + static void ipe_set_dmverity_signature(struct ipe_bdev *blob, 210 + const void *value, 211 + size_t size) 212 + { 213 + blob->dm_verity_signed = size > 0 && value; 214 + } 215 + #else 216 + static inline void ipe_set_dmverity_signature(struct ipe_bdev *blob, 217 + const void *value, 218 + size_t size) 219 + { 220 + } 221 + #endif /* CONFIG_IPE_PROP_DM_VERITY_SIGNATURE */ 222 + 223 + /** 224 + * ipe_bdev_setintegrity() - Save integrity data from a bdev to IPE's LSM blob. 225 + * @bdev: Supplies a pointer to a block_device that contains the LSM blob. 226 + * @type: Supplies the integrity type. 227 + * @value: Supplies the value to store. 228 + * @size: The size of @value. 229 + * 230 + * This hook is currently used to save dm-verity's root hash or the existence 231 + * of a validated signed dm-verity root hash into LSM blob. 232 + * 233 + * Return: %0 on success. If an error occurs, the function will return the 234 + * -errno. 235 + */ 236 + int ipe_bdev_setintegrity(struct block_device *bdev, enum lsm_integrity_type type, 237 + const void *value, size_t size) 238 + { 239 + const struct dm_verity_digest *digest = NULL; 240 + struct ipe_bdev *blob = ipe_bdev(bdev); 241 + struct digest_info *info = NULL; 242 + 243 + if (type == LSM_INT_DMVERITY_SIG_VALID) { 244 + ipe_set_dmverity_signature(blob, value, size); 245 + 246 + return 0; 247 + } 248 + 249 + if (type != LSM_INT_DMVERITY_ROOTHASH) 250 + return -EINVAL; 251 + 252 + if (!value) { 253 + ipe_digest_free(blob->root_hash); 254 + blob->root_hash = NULL; 255 + 256 + return 0; 257 + } 258 + digest = value; 259 + 260 + info = kzalloc(sizeof(*info), GFP_KERNEL); 261 + if (!info) 262 + return -ENOMEM; 263 + 264 + info->digest = kmemdup(digest->digest, digest->digest_len, GFP_KERNEL); 265 + if (!info->digest) 266 + goto err; 267 + 268 + info->alg = kstrdup(digest->alg, GFP_KERNEL); 269 + if (!info->alg) 270 + goto err; 271 + 272 + info->digest_len = digest->digest_len; 273 + 274 + ipe_digest_free(blob->root_hash); 275 + blob->root_hash = info; 276 + 277 + return 0; 278 + err: 279 + ipe_digest_free(info); 280 + 281 + return -ENOMEM; 282 + } 283 + #endif /* CONFIG_IPE_PROP_DM_VERITY */
+8
security/ipe/hooks.h
··· 8 8 #include <linux/fs.h> 9 9 #include <linux/binfmts.h> 10 10 #include <linux/security.h> 11 + #include <linux/blk_types.h> 11 12 12 13 enum ipe_hook_type { 13 14 IPE_HOOK_BPRM_CHECK = 0, ··· 35 34 int ipe_kernel_load_data(enum kernel_load_data_id id, bool contents); 36 35 37 36 void ipe_unpack_initramfs(void); 37 + 38 + #ifdef CONFIG_IPE_PROP_DM_VERITY 39 + void ipe_bdev_free_security(struct block_device *bdev); 40 + 41 + int ipe_bdev_setintegrity(struct block_device *bdev, enum lsm_integrity_type type, 42 + const void *value, size_t len); 43 + #endif /* CONFIG_IPE_PROP_DM_VERITY */ 38 44 39 45 #endif /* _IPE_HOOKS_H */
+15
security/ipe/ipe.c
··· 7 7 #include "ipe.h" 8 8 #include "eval.h" 9 9 #include "hooks.h" 10 + #include "eval.h" 10 11 11 12 bool ipe_enabled; 12 13 13 14 static struct lsm_blob_sizes ipe_blobs __ro_after_init = { 14 15 .lbs_superblock = sizeof(struct ipe_superblock), 16 + #ifdef CONFIG_IPE_PROP_DM_VERITY 17 + .lbs_bdev = sizeof(struct ipe_bdev), 18 + #endif /* CONFIG_IPE_PROP_DM_VERITY */ 15 19 }; 16 20 17 21 static const struct lsm_id ipe_lsmid = { ··· 28 24 return sb->s_security + ipe_blobs.lbs_superblock; 29 25 } 30 26 27 + #ifdef CONFIG_IPE_PROP_DM_VERITY 28 + struct ipe_bdev *ipe_bdev(struct block_device *b) 29 + { 30 + return b->bd_security + ipe_blobs.lbs_bdev; 31 + } 32 + #endif /* CONFIG_IPE_PROP_DM_VERITY */ 33 + 31 34 static struct security_hook_list ipe_hooks[] __ro_after_init = { 32 35 LSM_HOOK_INIT(bprm_check_security, ipe_bprm_check_security), 33 36 LSM_HOOK_INIT(mmap_file, ipe_mmap_file), ··· 42 31 LSM_HOOK_INIT(kernel_read_file, ipe_kernel_read_file), 43 32 LSM_HOOK_INIT(kernel_load_data, ipe_kernel_load_data), 44 33 LSM_HOOK_INIT(initramfs_populated, ipe_unpack_initramfs), 34 + #ifdef CONFIG_IPE_PROP_DM_VERITY 35 + LSM_HOOK_INIT(bdev_free_security, ipe_bdev_free_security), 36 + LSM_HOOK_INIT(bdev_setintegrity, ipe_bdev_setintegrity), 37 + #endif /* CONFIG_IPE_PROP_DM_VERITY */ 45 38 }; 46 39 47 40 /**
+4
security/ipe/ipe.h
··· 16 16 17 17 extern bool ipe_enabled; 18 18 19 + #ifdef CONFIG_IPE_PROP_DM_VERITY 20 + struct ipe_bdev *ipe_bdev(struct block_device *b); 21 + #endif /* CONFIG_IPE_PROP_DM_VERITY */ 22 + 19 23 #endif /* _IPE_H */
+3
security/ipe/policy.h
··· 33 33 enum ipe_prop_type { 34 34 IPE_PROP_BOOT_VERIFIED_FALSE, 35 35 IPE_PROP_BOOT_VERIFIED_TRUE, 36 + IPE_PROP_DMV_ROOTHASH, 37 + IPE_PROP_DMV_SIG_FALSE, 38 + IPE_PROP_DMV_SIG_TRUE, 36 39 __IPE_PROP_MAX 37 40 }; 38 41
+23 -1
security/ipe/policy_parser.c
··· 11 11 12 12 #include "policy.h" 13 13 #include "policy_parser.h" 14 + #include "digest.h" 14 15 15 16 #define START_COMMENT '#' 16 17 #define IPE_POLICY_DELIM " \t" ··· 222 221 223 222 list_for_each_entry_safe(p, t, &r->props, next) { 224 223 list_del(&p->next); 224 + ipe_digest_free(p->value); 225 225 kfree(p); 226 226 } 227 227 ··· 275 273 static const match_table_t property_tokens = { 276 274 {IPE_PROP_BOOT_VERIFIED_FALSE, "boot_verified=FALSE"}, 277 275 {IPE_PROP_BOOT_VERIFIED_TRUE, "boot_verified=TRUE"}, 276 + {IPE_PROP_DMV_ROOTHASH, "dmverity_roothash=%s"}, 277 + {IPE_PROP_DMV_SIG_FALSE, "dmverity_signature=FALSE"}, 278 + {IPE_PROP_DMV_SIG_TRUE, "dmverity_signature=TRUE"}, 278 279 {IPE_PROP_INVALID, NULL} 279 280 }; 280 281 ··· 300 295 struct ipe_prop *p = NULL; 301 296 int rc = 0; 302 297 int token; 298 + char *dup = NULL; 303 299 304 300 p = kzalloc(sizeof(*p), GFP_KERNEL); 305 301 if (!p) ··· 309 303 token = match_token(t, property_tokens, args); 310 304 311 305 switch (token) { 306 + case IPE_PROP_DMV_ROOTHASH: 307 + dup = match_strdup(&args[0]); 308 + if (!dup) { 309 + rc = -ENOMEM; 310 + goto err; 311 + } 312 + p->value = ipe_digest_parse(dup); 313 + if (IS_ERR(p->value)) { 314 + rc = PTR_ERR(p->value); 315 + goto err; 316 + } 317 + fallthrough; 312 318 case IPE_PROP_BOOT_VERIFIED_FALSE: 313 319 case IPE_PROP_BOOT_VERIFIED_TRUE: 320 + case IPE_PROP_DMV_SIG_FALSE: 321 + case IPE_PROP_DMV_SIG_TRUE: 314 322 p->type = token; 315 323 break; 316 324 default: ··· 335 315 goto err; 336 316 list_add_tail(&p->next, &r->props); 337 317 318 + out: 319 + kfree(dup); 338 320 return rc; 339 321 err: 340 322 kfree(p); 341 - return rc; 323 + goto out; 342 324 } 343 325 344 326 /**
+12 -11
security/security.c
··· 5739 5739 * Please note that the new hook should be invoked every time the security 5740 5740 * information is updated to keep these data current. For example, in dm-verity, 5741 5741 * if the mapping table is reloaded and configured to use a different dm-verity 5742 - * target with a new roothash and signing information, the previously stored data 5743 - * in the LSM blob will become obsolete. It is crucial to re-invoke the hook to 5744 - * refresh these data and ensure they are up to date. This necessity arises from 5745 - * the design of device-mapper, where a device-mapper device is first created, and 5746 - * then targets are subsequently loaded into it. These targets can be modified 5747 - * multiple times during the device's lifetime. Therefore, while the LSM blob is 5748 - * allocated during the creation of the block device, its actual contents are 5749 - * not initialized at this stage and can change substantially over time. This 5750 - * includes alterations from data that the LSMs 'trusts' to those they do not, 5751 - * making it essential to handle these changes correctly. Failure to address 5752 - * this dynamic aspect could potentially allow for bypassing LSM checks. 5742 + * target with a new roothash and signing information, the previously stored 5743 + * data in the LSM blob will become obsolete. It is crucial to re-invoke the 5744 + * hook to refresh these data and ensure they are up to date. This necessity 5745 + * arises from the design of device-mapper, where a device-mapper device is 5746 + * first created, and then targets are subsequently loaded into it. These 5747 + * targets can be modified multiple times during the device's lifetime. 5748 + * Therefore, while the LSM blob is allocated during the creation of the block 5749 + * device, its actual contents are not initialized at this stage and can change 5750 + * substantially over time. This includes alterations from data that the LSMs 5751 + * 'trusts' to those they do not, making it essential to handle these changes 5752 + * correctly. Failure to address this dynamic aspect could potentially allow 5753 + * for bypassing LSM checks. 5753 5754 * 5754 5755 * Return: Returns 0 on success, negative values on failure. 5755 5756 */