]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ipe: introduce 'boot_verified' as a trust provider
authorFan Wu <wufan@linux.microsoft.com>
Sat, 3 Aug 2024 06:08:20 +0000 (23:08 -0700)
committerPaul Moore <paul@paul-moore.com>
Tue, 20 Aug 2024 18:01:52 +0000 (14:01 -0400)
IPE is designed to provide system level trust guarantees, this usually
implies that trust starts from bootup with a hardware root of trust,
which validates the bootloader. After this, the bootloader verifies
the kernel and the initramfs.

As there's no currently supported integrity method for initramfs, and
it's typically already verified by the bootloader. This patch introduces
a new IPE property `boot_verified` which allows author of IPE policy to
indicate trust for files from initramfs.

The implementation of this feature utilizes the newly added
`initramfs_populated` hook. This hook marks the superblock of the rootfs
after the initramfs has been unpacked into it.

Before mounting the real rootfs on top of the initramfs, initramfs
script will recursively remove all files and directories on the
initramfs. This is typically implemented by using switch_root(8)
(https://man7.org/linux/man-pages/man8/switch_root.8.html).
Therefore the initramfs will be empty and not accessible after the real
rootfs takes over. It is advised to switch to a different policy
that doesn't rely on the `boot_verified` property after this point.
This ensures that the trust policies remain relevant and effective
throughout the system's operation.

Signed-off-by: Deven Bowers <deven.desai@linux.microsoft.com>
Signed-off-by: Fan Wu <wufan@linux.microsoft.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
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

index 1739327f082bb8d5efcb92004a655901a8b766d6..d73d73dfed5253ff11a42f28436a04143f0d9d5d 100644 (file)
 
 struct ipe_policy __rcu *ipe_active_policy;
 
+#define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb)
+
+/**
+ * build_ipe_sb_ctx() - Build initramfs field of an ipe evaluation context.
+ * @ctx: Supplies a pointer to the context to be populated.
+ * @file: Supplies the file struct of the file triggered IPE event.
+ */
+static void build_ipe_sb_ctx(struct ipe_eval_ctx *ctx, const struct file *const file)
+{
+       ctx->initramfs = ipe_sb(FILE_SUPERBLOCK(file))->initramfs;
+}
+
 /**
  * ipe_build_eval_ctx() - Build an ipe evaluation context.
  * @ctx: Supplies a pointer to the context to be populated.
@@ -28,6 +40,22 @@ void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx,
 {
        ctx->file = file;
        ctx->op = op;
+
+       if (file)
+               build_ipe_sb_ctx(ctx, file);
+}
+
+/**
+ * evaluate_boot_verified() - Evaluate @ctx for the boot verified property.
+ * @ctx: Supplies a pointer to the context being evaluated.
+ *
+ * Return:
+ * * %true     - The current @ctx match the @p
+ * * %false    - The current @ctx doesn't match the @p
+ */
+static bool evaluate_boot_verified(const struct ipe_eval_ctx *const ctx)
+{
+       return ctx->initramfs;
 }
 
 /**
@@ -35,8 +63,8 @@ void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx,
  * @ctx: Supplies a pointer to the context to be evaluated.
  * @p: Supplies a pointer to the property to be evaluated.
  *
- * This is a placeholder. The actual function will be introduced in the
- * latter commits.
+ * This function Determines whether the specified @ctx
+ * matches the conditions defined by a rule property @p.
  *
  * Return:
  * * %true     - The current @ctx match the @p
@@ -45,7 +73,14 @@ void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx,
 static bool evaluate_property(const struct ipe_eval_ctx *const ctx,
                              struct ipe_prop *p)
 {
-       return false;
+       switch (p->type) {
+       case IPE_PROP_BOOT_VERIFIED_FALSE:
+               return !evaluate_boot_verified(ctx);
+       case IPE_PROP_BOOT_VERIFIED_TRUE:
+               return evaluate_boot_verified(ctx);
+       default:
+               return false;
+       }
 }
 
 /**
index 00ed8ceca10e8aea7b3cbedf208967238599fa61..0fa6492354ddbef407c4673d1011ea175f3e24fc 100644 (file)
 
 extern struct ipe_policy __rcu *ipe_active_policy;
 
+struct ipe_superblock {
+       bool initramfs;
+};
+
 struct ipe_eval_ctx {
        enum ipe_op_type op;
 
        const struct file *file;
+       bool initramfs;
 };
 
 void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx,
index 0da4607cc4bcc9b5bbd2a007a2bad36330ceb558..0bd351e2b32a8347ccb15feb75c0e24a70033efd 100644 (file)
@@ -4,6 +4,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/fs_struct.h>
 #include <linux/types.h>
 #include <linux/binfmts.h>
 #include <linux/mman.h>
@@ -182,3 +183,11 @@ int ipe_kernel_load_data(enum kernel_load_data_id id, bool contents)
        ipe_build_eval_ctx(&ctx, NULL, op);
        return ipe_evaluate_event(&ctx);
 }
+
+/**
+ * ipe_unpack_initramfs() - Mark the current rootfs as initramfs.
+ */
+void ipe_unpack_initramfs(void)
+{
+       ipe_sb(current->fs->root.mnt->mnt_sb)->initramfs = true;
+}
index c22c3336d27cd203a1490e89e6a00390681016ca..4de5fabebd548e321a7a2743445c1c9ea40c95d9 100644 (file)
@@ -22,4 +22,6 @@ int ipe_kernel_read_file(struct file *file, enum kernel_read_file_id id,
 
 int ipe_kernel_load_data(enum kernel_load_data_id id, bool contents);
 
+void ipe_unpack_initramfs(void);
+
 #endif /* _IPE_HOOKS_H */
index 729334812636304af9d6eaed8ddcf61c128b56ce..28555eadb7f3d7646d8b3aa0def0cf4b6a8b4aad 100644 (file)
@@ -5,9 +5,11 @@
 #include <uapi/linux/lsm.h>
 
 #include "ipe.h"
+#include "eval.h"
 #include "hooks.h"
 
 static struct lsm_blob_sizes ipe_blobs __ro_after_init = {
+       .lbs_superblock = sizeof(struct ipe_superblock),
 };
 
 static const struct lsm_id ipe_lsmid = {
@@ -15,12 +17,18 @@ static const struct lsm_id ipe_lsmid = {
        .id = LSM_ID_IPE,
 };
 
+struct ipe_superblock *ipe_sb(const struct super_block *sb)
+{
+       return sb->s_security + ipe_blobs.lbs_superblock;
+}
+
 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),
        LSM_HOOK_INIT(file_mprotect, ipe_file_mprotect),
        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),
 };
 
 /**
index adc3c45e9f531452dedb9d86a773053da4636ab3..7f1c818193a029c19599c2ceb3c014930dfd353a 100644 (file)
@@ -12,5 +12,6 @@
 #define pr_fmt(fmt) "ipe: " fmt
 
 #include <linux/lsm_hooks.h>
+struct ipe_superblock *ipe_sb(const struct super_block *sb);
 
 #endif /* _IPE_H */
index 8292ffaaff12e960ddb007b538110b4e69789280..69ca8cdecd64e75581c6ea5563a244ba9e0a03af 100644 (file)
@@ -30,6 +30,8 @@ enum ipe_action_type {
 #define IPE_ACTION_INVALID __IPE_ACTION_MAX
 
 enum ipe_prop_type {
+       IPE_PROP_BOOT_VERIFIED_FALSE,
+       IPE_PROP_BOOT_VERIFIED_TRUE,
        __IPE_PROP_MAX
 };
 
index 0926b442e32a64b531c958aa8791ea091e1be8e7..67e3fc48f7a648848b7231b2eabef527ecf29e45 100644 (file)
@@ -270,13 +270,19 @@ static enum ipe_action_type parse_action(char *t)
        return match_token(t, action_tokens, args);
 }
 
+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_INVALID,              NULL}
+};
+
 /**
  * parse_property() - Parse a rule property given a token string.
  * @t: Supplies the token string to be parsed.
  * @r: Supplies the ipe_rule the parsed property will be associated with.
  *
- * This is a placeholder. The actual function will be introduced in the
- * latter commits.
+ * This function parses and associates a property with an IPE rule based
+ * on a token string.
  *
  * Return:
  * * %0                - Success
@@ -285,7 +291,34 @@ static enum ipe_action_type parse_action(char *t)
  */
 static int parse_property(char *t, struct ipe_rule *r)
 {
-       return -EBADMSG;
+       substring_t args[MAX_OPT_ARGS];
+       struct ipe_prop *p = NULL;
+       int rc = 0;
+       int token;
+
+       p = kzalloc(sizeof(*p), GFP_KERNEL);
+       if (!p)
+               return -ENOMEM;
+
+       token = match_token(t, property_tokens, args);
+
+       switch (token) {
+       case IPE_PROP_BOOT_VERIFIED_FALSE:
+       case IPE_PROP_BOOT_VERIFIED_TRUE:
+               p->type = token;
+               break;
+       default:
+               rc = -EBADMSG;
+               break;
+       }
+       if (rc)
+               goto err;
+       list_add_tail(&p->next, &r->props);
+
+       return rc;
+err:
+       kfree(p);
+       return rc;
 }
 
 /**