]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ipe: add support for dm-verity as a trust provider
authorDeven Bowers <deven.desai@linux.microsoft.com>
Sat, 3 Aug 2024 06:08:27 +0000 (23:08 -0700)
committerPaul Moore <paul@paul-moore.com>
Tue, 20 Aug 2024 18:02:45 +0000 (14:02 -0400)
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>
14 files changed:
security/ipe/Kconfig
security/ipe/Makefile
security/ipe/audit.c
security/ipe/digest.c [new file with mode: 0644]
security/ipe/digest.h [new file with mode: 0644]
security/ipe/eval.c
security/ipe/eval.h
security/ipe/hooks.c
security/ipe/hooks.h
security/ipe/ipe.c
security/ipe/ipe.h
security/ipe/policy.h
security/ipe/policy_parser.c
security/security.c

index ac4d558e69d59ccb3f89e4dba14e96eb1106ddbf..8279dddf92adeb8a785543aef7222f8a150936f7 100644 (file)
@@ -8,6 +8,8 @@ menuconfig SECURITY_IPE
        depends on SECURITY && SECURITYFS && AUDIT && AUDITSYSCALL
        select PKCS7_MESSAGE_PARSER
        select SYSTEM_DATA_VERIFICATION
+       select IPE_PROP_DM_VERITY if DM_VERITY
+       select IPE_PROP_DM_VERITY_SIGNATURE if DM_VERITY && DM_VERITY_VERIFY_ROOTHASH_SIG
        help
          This option enables the Integrity Policy Enforcement LSM
          allowing users to define a policy to enforce a trust-based access
@@ -15,3 +17,28 @@ menuconfig SECURITY_IPE
          admins to reconfigure trust requirements on the fly.
 
          If unsure, answer N.
+
+if SECURITY_IPE
+menu "IPE Trust Providers"
+
+config IPE_PROP_DM_VERITY
+       bool "Enable support for dm-verity based on root hash"
+       depends on DM_VERITY
+       help
+         This option enables the 'dmverity_roothash' property within IPE
+         policies. The property evaluates to TRUE when a file from a dm-verity
+         volume is evaluated, and the volume's root hash matches the value
+         supplied in the policy.
+
+config IPE_PROP_DM_VERITY_SIGNATURE
+       bool "Enable support for dm-verity based on root hash signature"
+       depends on DM_VERITY && DM_VERITY_VERIFY_ROOTHASH_SIG
+       help
+         This option enables the 'dmverity_signature' property within IPE
+         policies. The property evaluates to TRUE when a file from a dm-verity
+         volume, which has been mounted with a valid signed root hash,
+         is evaluated.
+
+endmenu
+
+endif
index 62caccba14b4e0a7e1ac209bf9e25459548ef357..e1019bb9f0f321bcfd3557fcc07d548bf9ba60ed 100644 (file)
@@ -6,6 +6,7 @@
 #
 
 obj-$(CONFIG_SECURITY_IPE) += \
+       digest.o \
        eval.o \
        hooks.o \
        fs.o \
index 5af150d99d631fea326bc934f622ce404b040623..8e21879e96c7a3f6368e34277af10c8ceaf591eb 100644 (file)
@@ -13,6 +13,7 @@
 #include "hooks.h"
 #include "policy.h"
 #include "audit.h"
+#include "digest.h"
 
 #define ACTSTR(x) ((x) == IPE_ACTION_ALLOW ? "ALLOW" : "DENY")
 
@@ -52,8 +53,22 @@ static const char *const audit_hook_names[__IPE_HOOK_MAX] = {
 static const char *const audit_prop_names[__IPE_PROP_MAX] = {
        "boot_verified=FALSE",
        "boot_verified=TRUE",
+       "dmverity_roothash=",
+       "dmverity_signature=FALSE",
+       "dmverity_signature=TRUE",
 };
 
+/**
+ * audit_dmv_roothash() - audit the roothash of a dmverity_roothash property.
+ * @ab: Supplies a pointer to the audit_buffer to append to.
+ * @rh: Supplies a pointer to the digest structure.
+ */
+static void audit_dmv_roothash(struct audit_buffer *ab, const void *rh)
+{
+       audit_log_format(ab, "%s", audit_prop_names[IPE_PROP_DMV_ROOTHASH]);
+       ipe_digest_audit(ab, rh);
+}
+
 /**
  * audit_rule() - audit an IPE policy rule.
  * @ab: Supplies a pointer to the audit_buffer to append to.
@@ -65,8 +80,18 @@ static void audit_rule(struct audit_buffer *ab, const struct ipe_rule *r)
 
        audit_log_format(ab, " rule=\"op=%s ", audit_op_names[r->op]);
 
-       list_for_each_entry(ptr, &r->props, next)
-               audit_log_format(ab, "%s ", audit_prop_names[ptr->type]);
+       list_for_each_entry(ptr, &r->props, next) {
+               switch (ptr->type) {
+               case IPE_PROP_DMV_ROOTHASH:
+                       audit_dmv_roothash(ab, ptr->value);
+                       break;
+               default:
+                       audit_log_format(ab, "%s", audit_prop_names[ptr->type]);
+                       break;
+               }
+
+               audit_log_format(ab, " ");
+       }
 
        audit_log_format(ab, "action=%s\"", ACTSTR(r->action));
 }
diff --git a/security/ipe/digest.c b/security/ipe/digest.c
new file mode 100644 (file)
index 0000000..4937163
--- /dev/null
@@ -0,0 +1,118 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
+ */
+
+#include "digest.h"
+
+/**
+ * ipe_digest_parse() - parse a digest in IPE's policy.
+ * @valstr: Supplies the string parsed from the policy.
+ *
+ * Digests in IPE are defined in a standard way:
+ *     <alg_name>:<hex>
+ *
+ * Use this function to create a property to parse the digest
+ * consistently. The parsed digest will be saved in @value in IPE's
+ * policy.
+ *
+ * Return: The parsed digest_info structure on success. If an error occurs,
+ * the function will return the error value (via ERR_PTR).
+ */
+struct digest_info *ipe_digest_parse(const char *valstr)
+{
+       struct digest_info *info = NULL;
+       char *sep, *raw_digest;
+       size_t raw_digest_len;
+       u8 *digest = NULL;
+       char *alg = NULL;
+       int rc = 0;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return ERR_PTR(-ENOMEM);
+
+       sep = strchr(valstr, ':');
+       if (!sep) {
+               rc = -EBADMSG;
+               goto err;
+       }
+
+       alg = kstrndup(valstr, sep - valstr, GFP_KERNEL);
+       if (!alg) {
+               rc = -ENOMEM;
+               goto err;
+       }
+
+       raw_digest = sep + 1;
+       raw_digest_len = strlen(raw_digest);
+
+       info->digest_len = (raw_digest_len + 1) / 2;
+       digest = kzalloc(info->digest_len, GFP_KERNEL);
+       if (!digest) {
+               rc = -ENOMEM;
+               goto err;
+       }
+
+       rc = hex2bin(digest, raw_digest, info->digest_len);
+       if (rc < 0) {
+               rc = -EINVAL;
+               goto err;
+       }
+
+       info->alg = alg;
+       info->digest = digest;
+       return info;
+
+err:
+       kfree(alg);
+       kfree(digest);
+       kfree(info);
+       return ERR_PTR(rc);
+}
+
+/**
+ * ipe_digest_eval() - evaluate an IPE digest against another digest.
+ * @expected: Supplies the policy-provided digest value.
+ * @digest: Supplies the digest to compare against the policy digest value.
+ *
+ * Return:
+ * * %true     - digests match
+ * * %false    - digests do not match
+ */
+bool ipe_digest_eval(const struct digest_info *expected,
+                    const struct digest_info *digest)
+{
+       return (expected->digest_len == digest->digest_len) &&
+              (!strcmp(expected->alg, digest->alg)) &&
+              (!memcmp(expected->digest, digest->digest, expected->digest_len));
+}
+
+/**
+ * ipe_digest_free() - free an IPE digest.
+ * @info: Supplies a pointer the policy-provided digest to free.
+ */
+void ipe_digest_free(struct digest_info *info)
+{
+       if (IS_ERR_OR_NULL(info))
+               return;
+
+       kfree(info->alg);
+       kfree(info->digest);
+       kfree(info);
+}
+
+/**
+ * ipe_digest_audit() - audit a digest that was sourced from IPE's policy.
+ * @ab: Supplies the audit_buffer to append the formatted result.
+ * @info: Supplies a pointer to source the audit record from.
+ *
+ * Digests in IPE are audited in this format:
+ *     <alg_name>:<hex>
+ */
+void ipe_digest_audit(struct audit_buffer *ab, const struct digest_info *info)
+{
+       audit_log_untrustedstring(ab, info->alg);
+       audit_log_format(ab, ":");
+       audit_log_n_hex(ab, info->digest, info->digest_len);
+}
diff --git a/security/ipe/digest.h b/security/ipe/digest.h
new file mode 100644 (file)
index 0000000..52c9b38
--- /dev/null
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
+ */
+
+#ifndef _IPE_DIGEST_H
+#define _IPE_DIGEST_H
+
+#include <linux/types.h>
+#include <linux/audit.h>
+
+#include "policy.h"
+
+struct digest_info {
+       const char *alg;
+       const u8 *digest;
+       size_t digest_len;
+};
+
+struct digest_info *ipe_digest_parse(const char *valstr);
+void ipe_digest_free(struct digest_info *digest_info);
+void ipe_digest_audit(struct audit_buffer *ab, const struct digest_info *val);
+bool ipe_digest_eval(const struct digest_info *expected,
+                    const struct digest_info *digest);
+
+#endif /* _IPE_DIGEST_H */
index b14c957685501da328d640c1a49616daa7006032..2b80cc399ac3669b25936d6d0f8de61a1cde2a05 100644 (file)
 #include "eval.h"
 #include "policy.h"
 #include "audit.h"
+#include "digest.h"
 
 struct ipe_policy __rcu *ipe_active_policy;
 bool success_audit;
 bool enforce = true;
+#define INO_BLOCK_DEV(ino) ((ino)->i_sb->s_bdev)
 
 #define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb)
 
@@ -32,6 +34,23 @@ static void build_ipe_sb_ctx(struct ipe_eval_ctx *ctx, const struct file *const
        ctx->initramfs = ipe_sb(FILE_SUPERBLOCK(file))->initramfs;
 }
 
+#ifdef CONFIG_IPE_PROP_DM_VERITY
+/**
+ * build_ipe_bdev_ctx() - Build ipe_bdev field of an evaluation context.
+ * @ctx: Supplies a pointer to the context to be populated.
+ * @ino: Supplies the inode struct of the file triggered IPE event.
+ */
+static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
+{
+       if (INO_BLOCK_DEV(ino))
+               ctx->ipe_bdev = ipe_bdev(INO_BLOCK_DEV(ino));
+}
+#else
+static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
+{
+}
+#endif /* CONFIG_IPE_PROP_DM_VERITY */
+
 /**
  * ipe_build_eval_ctx() - Build an ipe evaluation context.
  * @ctx: Supplies a pointer to the context to be populated.
@@ -48,8 +67,10 @@ void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx,
        ctx->op = op;
        ctx->hook = hook;
 
-       if (file)
+       if (file) {
                build_ipe_sb_ctx(ctx, file);
+               build_ipe_bdev_ctx(ctx, d_real_inode(file->f_path.dentry));
+       }
 }
 
 /**
@@ -65,6 +86,70 @@ static bool evaluate_boot_verified(const struct ipe_eval_ctx *const ctx)
        return ctx->initramfs;
 }
 
+#ifdef CONFIG_IPE_PROP_DM_VERITY
+/**
+ * evaluate_dmv_roothash() - Evaluate @ctx against a dmv roothash property.
+ * @ctx: Supplies a pointer to the context being evaluated.
+ * @p: Supplies a pointer to the property being evaluated.
+ *
+ * Return:
+ * * %true     - The current @ctx match the @p
+ * * %false    - The current @ctx doesn't match the @p
+ */
+static bool evaluate_dmv_roothash(const struct ipe_eval_ctx *const ctx,
+                                 struct ipe_prop *p)
+{
+       return !!ctx->ipe_bdev &&
+              !!ctx->ipe_bdev->root_hash &&
+              ipe_digest_eval(p->value,
+                              ctx->ipe_bdev->root_hash);
+}
+#else
+static bool evaluate_dmv_roothash(const struct ipe_eval_ctx *const ctx,
+                                 struct ipe_prop *p)
+{
+       return false;
+}
+#endif /* CONFIG_IPE_PROP_DM_VERITY */
+
+#ifdef CONFIG_IPE_PROP_DM_VERITY_SIGNATURE
+/**
+ * evaluate_dmv_sig_false() - Evaluate @ctx against a dmv sig false property.
+ * @ctx: Supplies a pointer to the context being evaluated.
+ *
+ * Return:
+ * * %true     - The current @ctx match the property
+ * * %false    - The current @ctx doesn't match the property
+ */
+static bool evaluate_dmv_sig_false(const struct ipe_eval_ctx *const ctx)
+{
+       return !ctx->ipe_bdev || (!ctx->ipe_bdev->dm_verity_signed);
+}
+
+/**
+ * evaluate_dmv_sig_true() - Evaluate @ctx against a dmv sig true property.
+ * @ctx: Supplies a pointer to the context being evaluated.
+ *
+ * Return:
+ * * %true     - The current @ctx match the property
+ * * %false    - The current @ctx doesn't match the property
+ */
+static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx *const ctx)
+{
+       return !evaluate_dmv_sig_false(ctx);
+}
+#else
+static bool evaluate_dmv_sig_false(const struct ipe_eval_ctx *const ctx)
+{
+       return false;
+}
+
+static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx *const ctx)
+{
+       return false;
+}
+#endif /* CONFIG_IPE_PROP_DM_VERITY_SIGNATURE */
+
 /**
  * evaluate_property() - Analyze @ctx against a rule property.
  * @ctx: Supplies a pointer to the context to be evaluated.
@@ -85,6 +170,12 @@ static bool evaluate_property(const struct ipe_eval_ctx *const ctx,
                return !evaluate_boot_verified(ctx);
        case IPE_PROP_BOOT_VERIFIED_TRUE:
                return evaluate_boot_verified(ctx);
+       case IPE_PROP_DMV_ROOTHASH:
+               return evaluate_dmv_roothash(ctx, p);
+       case IPE_PROP_DMV_SIG_FALSE:
+               return evaluate_dmv_sig_false(ctx);
+       case IPE_PROP_DMV_SIG_TRUE:
+               return evaluate_dmv_sig_true(ctx);
        default:
                return false;
        }
index 80b74f55fa69ea6663da1836d3efe593c5c9700f..4901df0e136925cbbffd3c9cb68f08c540d5a037 100644 (file)
@@ -22,12 +22,24 @@ struct ipe_superblock {
        bool initramfs;
 };
 
+#ifdef CONFIG_IPE_PROP_DM_VERITY
+struct ipe_bdev {
+#ifdef CONFIG_IPE_PROP_DM_VERITY_SIGNATURE
+       bool dm_verity_signed;
+#endif /* CONFIG_IPE_PROP_DM_VERITY_SIGNATURE */
+       struct digest_info *root_hash;
+};
+#endif /* CONFIG_IPE_PROP_DM_VERITY */
+
 struct ipe_eval_ctx {
        enum ipe_op_type op;
        enum ipe_hook_type hook;
 
        const struct file *file;
        bool initramfs;
+#ifdef CONFIG_IPE_PROP_DM_VERITY
+       const struct ipe_bdev *ipe_bdev;
+#endif /* CONFIG_IPE_PROP_DM_VERITY */
 };
 
 enum ipe_match {
index e92228723784923a3e249a574b9a53b281a3e5ee..0b7c66dc15d3693205c938add3c4f0d4c037746e 100644 (file)
@@ -8,10 +8,12 @@
 #include <linux/types.h>
 #include <linux/binfmts.h>
 #include <linux/mman.h>
+#include <linux/blk_types.h>
 
 #include "ipe.h"
 #include "hooks.h"
 #include "eval.h"
+#include "digest.h"
 
 /**
  * ipe_bprm_check_security() - ipe security hook function for bprm check.
@@ -191,3 +193,93 @@ void ipe_unpack_initramfs(void)
 {
        ipe_sb(current->fs->root.mnt->mnt_sb)->initramfs = true;
 }
+
+#ifdef CONFIG_IPE_PROP_DM_VERITY
+/**
+ * ipe_bdev_free_security() - Free IPE's LSM blob of block_devices.
+ * @bdev: Supplies a pointer to a block_device that contains the structure
+ *       to free.
+ */
+void ipe_bdev_free_security(struct block_device *bdev)
+{
+       struct ipe_bdev *blob = ipe_bdev(bdev);
+
+       ipe_digest_free(blob->root_hash);
+}
+
+#ifdef CONFIG_IPE_PROP_DM_VERITY_SIGNATURE
+static void ipe_set_dmverity_signature(struct ipe_bdev *blob,
+                                      const void *value,
+                                      size_t size)
+{
+       blob->dm_verity_signed = size > 0 && value;
+}
+#else
+static inline void ipe_set_dmverity_signature(struct ipe_bdev *blob,
+                                             const void *value,
+                                             size_t size)
+{
+}
+#endif /* CONFIG_IPE_PROP_DM_VERITY_SIGNATURE */
+
+/**
+ * ipe_bdev_setintegrity() - Save integrity data from a bdev to IPE's LSM blob.
+ * @bdev: Supplies a pointer to a block_device that contains the LSM blob.
+ * @type: Supplies the integrity type.
+ * @value: Supplies the value to store.
+ * @size: The size of @value.
+ *
+ * This hook is currently used to save dm-verity's root hash or the existence
+ * of a validated signed dm-verity root hash into LSM blob.
+ *
+ * Return: %0 on success. If an error occurs, the function will return the
+ * -errno.
+ */
+int ipe_bdev_setintegrity(struct block_device *bdev, enum lsm_integrity_type type,
+                         const void *value, size_t size)
+{
+       const struct dm_verity_digest *digest = NULL;
+       struct ipe_bdev *blob = ipe_bdev(bdev);
+       struct digest_info *info = NULL;
+
+       if (type == LSM_INT_DMVERITY_SIG_VALID) {
+               ipe_set_dmverity_signature(blob, value, size);
+
+               return 0;
+       }
+
+       if (type != LSM_INT_DMVERITY_ROOTHASH)
+               return -EINVAL;
+
+       if (!value) {
+               ipe_digest_free(blob->root_hash);
+               blob->root_hash = NULL;
+
+               return 0;
+       }
+       digest = value;
+
+       info = kzalloc(sizeof(*info), GFP_KERNEL);
+       if (!info)
+               return -ENOMEM;
+
+       info->digest = kmemdup(digest->digest, digest->digest_len, GFP_KERNEL);
+       if (!info->digest)
+               goto err;
+
+       info->alg = kstrdup(digest->alg, GFP_KERNEL);
+       if (!info->alg)
+               goto err;
+
+       info->digest_len = digest->digest_len;
+
+       ipe_digest_free(blob->root_hash);
+       blob->root_hash = info;
+
+       return 0;
+err:
+       ipe_digest_free(info);
+
+       return -ENOMEM;
+}
+#endif /* CONFIG_IPE_PROP_DM_VERITY */
index f4f0b544ddcce765a23b216252cec3b4bb7c7d2a..4d585fb6ada39c11a75d24ef647c9e98b7c2861c 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/fs.h>
 #include <linux/binfmts.h>
 #include <linux/security.h>
+#include <linux/blk_types.h>
 
 enum ipe_hook_type {
        IPE_HOOK_BPRM_CHECK = 0,
@@ -35,4 +36,11 @@ int ipe_kernel_load_data(enum kernel_load_data_id id, bool contents);
 
 void ipe_unpack_initramfs(void);
 
+#ifdef CONFIG_IPE_PROP_DM_VERITY
+void ipe_bdev_free_security(struct block_device *bdev);
+
+int ipe_bdev_setintegrity(struct block_device *bdev, enum lsm_integrity_type type,
+                         const void *value, size_t len);
+#endif /* CONFIG_IPE_PROP_DM_VERITY */
+
 #endif /* _IPE_HOOKS_H */
index 53f2196b9bcc923b5dd209215dd8cb2630c20c68..03c82a80744a72f1b5b337c5fdf86902b2ed0b80 100644 (file)
@@ -7,11 +7,15 @@
 #include "ipe.h"
 #include "eval.h"
 #include "hooks.h"
+#include "eval.h"
 
 bool ipe_enabled;
 
 static struct lsm_blob_sizes ipe_blobs __ro_after_init = {
        .lbs_superblock = sizeof(struct ipe_superblock),
+#ifdef CONFIG_IPE_PROP_DM_VERITY
+       .lbs_bdev = sizeof(struct ipe_bdev),
+#endif /* CONFIG_IPE_PROP_DM_VERITY */
 };
 
 static const struct lsm_id ipe_lsmid = {
@@ -24,6 +28,13 @@ struct ipe_superblock *ipe_sb(const struct super_block *sb)
        return sb->s_security + ipe_blobs.lbs_superblock;
 }
 
+#ifdef CONFIG_IPE_PROP_DM_VERITY
+struct ipe_bdev *ipe_bdev(struct block_device *b)
+{
+       return b->bd_security + ipe_blobs.lbs_bdev;
+}
+#endif /* CONFIG_IPE_PROP_DM_VERITY */
+
 static struct security_hook_list ipe_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(bprm_check_security, ipe_bprm_check_security),
        LSM_HOOK_INIT(mmap_file, ipe_mmap_file),
@@ -31,6 +42,10 @@ static struct security_hook_list ipe_hooks[] __ro_after_init = {
        LSM_HOOK_INIT(kernel_read_file, ipe_kernel_read_file),
        LSM_HOOK_INIT(kernel_load_data, ipe_kernel_load_data),
        LSM_HOOK_INIT(initramfs_populated, ipe_unpack_initramfs),
+#ifdef CONFIG_IPE_PROP_DM_VERITY
+       LSM_HOOK_INIT(bdev_free_security, ipe_bdev_free_security),
+       LSM_HOOK_INIT(bdev_setintegrity, ipe_bdev_setintegrity),
+#endif /* CONFIG_IPE_PROP_DM_VERITY */
 };
 
 /**
index 4aa18d1d05254e44e2230f9a22ec62da0d9b17e4..01f46286e383d4bd295dab7e472ddd134c1eba59 100644 (file)
@@ -16,4 +16,8 @@ struct ipe_superblock *ipe_sb(const struct super_block *sb);
 
 extern bool ipe_enabled;
 
+#ifdef CONFIG_IPE_PROP_DM_VERITY
+struct ipe_bdev *ipe_bdev(struct block_device *b);
+#endif /* CONFIG_IPE_PROP_DM_VERITY */
+
 #endif /* _IPE_H */
index ffd60cc7fda68aae99890056daf7f006891ad199..26776092c7100d894584786211574116708378cf 100644 (file)
@@ -33,6 +33,9 @@ enum ipe_action_type {
 enum ipe_prop_type {
        IPE_PROP_BOOT_VERIFIED_FALSE,
        IPE_PROP_BOOT_VERIFIED_TRUE,
+       IPE_PROP_DMV_ROOTHASH,
+       IPE_PROP_DMV_SIG_FALSE,
+       IPE_PROP_DMV_SIG_TRUE,
        __IPE_PROP_MAX
 };
 
index 67e3fc48f7a648848b7231b2eabef527ecf29e45..c3b7639df5323e7d7c50931c62463062ac8d97d4 100644 (file)
@@ -11,6 +11,7 @@
 
 #include "policy.h"
 #include "policy_parser.h"
+#include "digest.h"
 
 #define START_COMMENT  '#'
 #define IPE_POLICY_DELIM " \t"
@@ -221,6 +222,7 @@ static void free_rule(struct ipe_rule *r)
 
        list_for_each_entry_safe(p, t, &r->props, next) {
                list_del(&p->next);
+               ipe_digest_free(p->value);
                kfree(p);
        }
 
@@ -273,6 +275,9 @@ static enum ipe_action_type parse_action(char *t)
 static const match_table_t property_tokens = {
        {IPE_PROP_BOOT_VERIFIED_FALSE,  "boot_verified=FALSE"},
        {IPE_PROP_BOOT_VERIFIED_TRUE,   "boot_verified=TRUE"},
+       {IPE_PROP_DMV_ROOTHASH,         "dmverity_roothash=%s"},
+       {IPE_PROP_DMV_SIG_FALSE,        "dmverity_signature=FALSE"},
+       {IPE_PROP_DMV_SIG_TRUE,         "dmverity_signature=TRUE"},
        {IPE_PROP_INVALID,              NULL}
 };
 
@@ -295,6 +300,7 @@ static int parse_property(char *t, struct ipe_rule *r)
        struct ipe_prop *p = NULL;
        int rc = 0;
        int token;
+       char *dup = NULL;
 
        p = kzalloc(sizeof(*p), GFP_KERNEL);
        if (!p)
@@ -303,8 +309,22 @@ static int parse_property(char *t, struct ipe_rule *r)
        token = match_token(t, property_tokens, args);
 
        switch (token) {
+       case IPE_PROP_DMV_ROOTHASH:
+               dup = match_strdup(&args[0]);
+               if (!dup) {
+                       rc = -ENOMEM;
+                       goto err;
+               }
+               p->value = ipe_digest_parse(dup);
+               if (IS_ERR(p->value)) {
+                       rc = PTR_ERR(p->value);
+                       goto err;
+               }
+               fallthrough;
        case IPE_PROP_BOOT_VERIFIED_FALSE:
        case IPE_PROP_BOOT_VERIFIED_TRUE:
+       case IPE_PROP_DMV_SIG_FALSE:
+       case IPE_PROP_DMV_SIG_TRUE:
                p->type = token;
                break;
        default:
@@ -315,10 +335,12 @@ static int parse_property(char *t, struct ipe_rule *r)
                goto err;
        list_add_tail(&p->next, &r->props);
 
+out:
+       kfree(dup);
        return rc;
 err:
        kfree(p);
-       return rc;
+       goto out;
 }
 
 /**
index c7feaa885a0e7673ae6379e660b92020350286ec..3160a017358162ffc4cdb74d54bfc359b64a3ca9 100644 (file)
@@ -5739,17 +5739,18 @@ EXPORT_SYMBOL(security_bdev_free);
  * Please note that the new hook should be invoked every time the security
  * information is updated to keep these data current. For example, in dm-verity,
  * if the mapping table is reloaded and configured to use a different dm-verity
- * target with a new roothash and signing information, the previously stored data
- * in the LSM blob will become obsolete. It is crucial to re-invoke the hook to
- * refresh these data and ensure they are up to date. This necessity arises from
- * the design of device-mapper, where a device-mapper device is first created, and
- * then targets are subsequently loaded into it. These targets can be modified
- * multiple times during the device's lifetime. Therefore, while the LSM blob is
- * allocated during the creation of the block device, its actual contents are
- * not initialized at this stage and can change substantially over time. This
- * includes alterations from data that the LSMs 'trusts' to those they do not,
- * making it essential to handle these changes correctly. Failure to address
- * this dynamic aspect could potentially allow for bypassing LSM checks.
+ * target with a new roothash and signing information, the previously stored
+ * data in the LSM blob will become obsolete. It is crucial to re-invoke the
+ * hook to refresh these data and ensure they are up to date. This necessity
+ * arises from the design of device-mapper, where a device-mapper device is
+ * first created, and then targets are subsequently loaded into it. These
+ * targets can be modified multiple times during the device's lifetime.
+ * Therefore, while the LSM blob is allocated during the creation of the block
+ * device, its actual contents are not initialized at this stage and can change
+ * substantially over time. This includes alterations from data that the LSMs
+ * 'trusts' to those they do not, making it essential to handle these changes
+ * correctly. Failure to address this dynamic aspect could potentially allow
+ * for bypassing LSM checks.
  *
  * Return: Returns 0 on success, negative values on failure.
  */