@@ -68,4 +68,6 @@ config IPE_AUDIT_HASH_ALG
default "sha384" if IPE_AUDIT_HASH_SHA384
default "sha512" if IPE_AUDIT_HASH_SHA512
+source "security/ipe/modules/Kconfig"
+
endif
@@ -13,6 +13,7 @@ obj-$(CONFIG_SECURITY_IPE) += \
fs.o \
hooks.o \
ipe.o \
+ modules/ \
modules.o \
parsers/ \
parsers.o \
@@ -11,10 +11,62 @@
#include "modules/ipe_module.h"
#include "audit.h"
+#include <linux/fs.h>
+#include <linux/types.h>
#include <linux/slab.h>
#include <linux/file.h>
#include <linux/sched.h>
#include <linux/rcupdate.h>
+#include <linux/spinlock.h>
+
+static struct super_block *pinned_sb;
+static DEFINE_SPINLOCK(pin_lock);
+
+#define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb)
+
+/**
+ * pin_sb: pin the underlying superblock of @f, marking it as trusted
+ * @f: Supplies a file structure to source the super_block from.
+ */
+static void pin_sb(const struct file *f)
+{
+ if (!f)
+ return;
+
+ spin_lock(&pin_lock);
+
+ if (pinned_sb)
+ goto out;
+
+ pinned_sb = FILE_SUPERBLOCK(f);
+
+out:
+ spin_unlock(&pin_lock);
+}
+
+/**
+ * from_pinned: determine whether @f is source from the pinned super_block.
+ * @f: Supplies a file structure to check against the pinned super_block.
+ *
+ * Return:
+ * true - @f is sourced from the pinned super_block
+ * false - @f is not sourced from the pinned super_block
+ */
+static bool from_pinned(const struct file *f)
+{
+ bool rv;
+
+ if (!f)
+ return false;
+
+ spin_lock(&pin_lock);
+
+ rv = !IS_ERR_OR_NULL(pinned_sb) && pinned_sb == FILE_SUPERBLOCK(f);
+
+ spin_unlock(&pin_lock);
+
+ return rv;
+}
/**
* build_ctx: Build an evaluation context.
@@ -42,6 +94,7 @@ static struct ipe_eval_ctx *build_ctx(const struct file *file,
ctx->op = op;
ctx->hook = hook;
ctx->ci_ctx = ipe_current_ctx();
+ ctx->from_init_sb = from_pinned(file);
return ctx;
}
@@ -145,6 +198,9 @@ int ipe_process_event(const struct file *file, enum ipe_operation op,
int rc = 0;
struct ipe_eval_ctx *ctx = NULL;
+ if (op == ipe_operation_exec)
+ pin_sb(file);
+
ctx = build_ctx(file, op, hook);
if (IS_ERR(ctx))
return PTR_ERR(ctx);
@@ -154,3 +210,18 @@ int ipe_process_event(const struct file *file, enum ipe_operation op,
free_ctx(ctx);
return rc;
}
+
+/**
+ * ipe_invalidate_pinned_sb: if @mnt_sb is the pinned superblock, ensure
+ * nothing can match it again.
+ * @mnt_sb: super_block to check against the pinned super_block
+ */
+void ipe_invalidate_pinned_sb(const struct super_block *mnt_sb)
+{
+ spin_lock(&pin_lock);
+
+ if (!IS_ERR_OR_NULL(pinned_sb) && mnt_sb == pinned_sb)
+ pinned_sb = ERR_PTR(-EIO);
+
+ spin_unlock(&pin_lock);
+}
@@ -7,6 +7,7 @@
#define IPE_EVAL_H
#include <linux/file.h>
+#include <linux/types.h>
#include "ctx.h"
#include "hooks.h"
@@ -18,6 +19,8 @@ struct ipe_eval_ctx {
const struct file *file;
struct ipe_context *ci_ctx;
+
+ bool from_init_sb;
};
enum ipe_match {
@@ -30,4 +33,6 @@ enum ipe_match {
int ipe_process_event(const struct file *file, enum ipe_operation op,
enum ipe_hook hook);
+void ipe_invalidate_pinned_sb(const struct super_block *mnt_sb);
+
#endif /* IPE_EVAL_H */
@@ -205,3 +205,17 @@ int ipe_on_kernel_load_data(enum kernel_load_data_id id, bool contents)
return ipe_process_event(NULL, op, ipe_hook_kernel_load);
}
+
+/**
+ * ipe_bdev_free_security: free nested structures within IPE's LSM blob
+ * in super_blocks
+ * @mnt_sb: Supplies a pointer to a super_block that contains the structure
+ * to free.
+ *
+ * IPE does not have any structures with mnt_sb, but uses this hook to
+ * invalidate a pinned super_block.
+ */
+void ipe_sb_free_security(struct super_block *mnt_sb)
+{
+ ipe_invalidate_pinned_sb(mnt_sb);
+}
@@ -38,4 +38,6 @@ int ipe_on_kernel_read(struct file *file, enum kernel_read_file_id id,
int ipe_on_kernel_load_data(enum kernel_load_data_id id, bool contents);
+void ipe_sb_free_security(struct super_block *mnt_sb);
+
#endif /* IPE_HOOKS_H */
@@ -30,6 +30,7 @@ static struct security_hook_list ipe_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(file_mprotect, ipe_on_mprotect),
LSM_HOOK_INIT(kernel_read_file, ipe_on_kernel_read),
LSM_HOOK_INIT(kernel_load_data, ipe_on_kernel_load_data),
+ LSM_HOOK_INIT(sb_free_security, ipe_sb_free_security),
};
/**
@@ -107,3 +107,28 @@ int ipe_register_module(struct ipe_module *m)
return 0;
}
+
+/**
+ * ipe_bool_parse: parse a boolean in IPE's policy and associate
+ * it as @value in IPE's policy.
+ * @valstr: Supplies the string parsed from the policy
+ * @value: Supplies a pointer to be populated with the result.
+ *
+ * Modules can use this function for simple true/false values
+ * instead of defining their own.
+ *
+ * Return:
+ * 0 - OK
+ * !0 - Error
+ */
+int ipe_bool_parse(const char *valstr, void **value)
+{
+ if (!strcmp(valstr, "TRUE"))
+ *value = (void *)true;
+ else if (!strcmp(valstr, "FALSE"))
+ *value = (void *)false;
+ else
+ return -EBADMSG;
+
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,20 @@
+
+menu "IPE Trust Providers"
+
+config IPE_PROP_BOOT_VERIFIED
+ bool "Enable trust for initramfs"
+ depends on SECURITY_IPE
+ default N
+ help
+ This option enables the property 'boot_verified' in IPE policy.
+ This property 'pins' the initial superblock when something
+ is evaluated as an execution. This property will evaluate
+ to true when the file being evaluated originates from this
+ superblock.
+
+ This property is useful to authorize a signed initramfs.
+
+ If unsure, answer N.
+
+
+endmenu
new file mode 100644
@@ -0,0 +1,8 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Copyright (C) Microsoft Corporation. All rights reserved.
+#
+# Makefile for building the IPE module as part of the kernel tree.
+#
+
+obj-$(CONFIG_IPE_PROP_BOOT_VERIFIED) += boot_verified.o
new file mode 100644
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) Microsoft Corporation. All rights reserved.
+ */
+
+#include "ipe_module.h"
+
+#include <linux/fs.h>
+#include <linux/types.h>
+
+static bool bv_eval(const struct ipe_eval_ctx *ctx, const void *val)
+{
+ bool expect = (bool)val;
+
+ return expect == ctx->from_init_sb;
+}
+
+IPE_MODULE(bv) = {
+ .name = "boot_verified",
+ .version = 1,
+ .parse = ipe_bool_parse,
+ .free = NULL,
+ .eval = bv_eval,
+};
@@ -9,6 +9,8 @@
#include <linux/audit.h>
#include "../eval.h"
+int ipe_bool_parse(const char *valstr, void **value);
+
/**
* ipe_module: definition of an extensible module for IPE properties.
* These structures are used to implement 'key=value' pairs