105a35163SDeven Bowers // SPDX-License-Identifier: GPL-2.0 205a35163SDeven Bowers /* 305a35163SDeven Bowers * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved. 405a35163SDeven Bowers */ 505a35163SDeven Bowers 605a35163SDeven Bowers #include <linux/fs.h> 705a35163SDeven Bowers #include <linux/types.h> 805a35163SDeven Bowers #include <linux/slab.h> 905a35163SDeven Bowers #include <linux/file.h> 1005a35163SDeven Bowers #include <linux/sched.h> 1105a35163SDeven Bowers #include <linux/rcupdate.h> 12*f44554b5SDeven Bowers #include <linux/moduleparam.h> 1305a35163SDeven Bowers 1405a35163SDeven Bowers #include "ipe.h" 1505a35163SDeven Bowers #include "eval.h" 1605a35163SDeven Bowers #include "policy.h" 17*f44554b5SDeven Bowers #include "audit.h" 1805a35163SDeven Bowers 1905a35163SDeven Bowers struct ipe_policy __rcu *ipe_active_policy; 20*f44554b5SDeven Bowers bool success_audit; 2105a35163SDeven Bowers 22a8a74df1SFan Wu #define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb) 23a8a74df1SFan Wu 24a8a74df1SFan Wu /** 25a8a74df1SFan Wu * build_ipe_sb_ctx() - Build initramfs field of an ipe evaluation context. 26a8a74df1SFan Wu * @ctx: Supplies a pointer to the context to be populated. 27a8a74df1SFan Wu * @file: Supplies the file struct of the file triggered IPE event. 28a8a74df1SFan Wu */ 29a8a74df1SFan Wu static void build_ipe_sb_ctx(struct ipe_eval_ctx *ctx, const struct file *const file) 30a8a74df1SFan Wu { 31a8a74df1SFan Wu ctx->initramfs = ipe_sb(FILE_SUPERBLOCK(file))->initramfs; 32a8a74df1SFan Wu } 33a8a74df1SFan Wu 3405a35163SDeven Bowers /** 3552443cb6SDeven Bowers * ipe_build_eval_ctx() - Build an ipe evaluation context. 3652443cb6SDeven Bowers * @ctx: Supplies a pointer to the context to be populated. 3752443cb6SDeven Bowers * @file: Supplies a pointer to the file to associated with the evaluation. 3852443cb6SDeven Bowers * @op: Supplies the IPE policy operation associated with the evaluation. 39*f44554b5SDeven Bowers * @hook: Supplies the LSM hook associated with the evaluation. 4052443cb6SDeven Bowers */ 4152443cb6SDeven Bowers void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx, 4252443cb6SDeven Bowers const struct file *file, 43*f44554b5SDeven Bowers enum ipe_op_type op, 44*f44554b5SDeven Bowers enum ipe_hook_type hook) 4552443cb6SDeven Bowers { 4652443cb6SDeven Bowers ctx->file = file; 4752443cb6SDeven Bowers ctx->op = op; 48*f44554b5SDeven Bowers ctx->hook = hook; 49a8a74df1SFan Wu 50a8a74df1SFan Wu if (file) 51a8a74df1SFan Wu build_ipe_sb_ctx(ctx, file); 52a8a74df1SFan Wu } 53a8a74df1SFan Wu 54a8a74df1SFan Wu /** 55a8a74df1SFan Wu * evaluate_boot_verified() - Evaluate @ctx for the boot verified property. 56a8a74df1SFan Wu * @ctx: Supplies a pointer to the context being evaluated. 57a8a74df1SFan Wu * 58a8a74df1SFan Wu * Return: 59a8a74df1SFan Wu * * %true - The current @ctx match the @p 60a8a74df1SFan Wu * * %false - The current @ctx doesn't match the @p 61a8a74df1SFan Wu */ 62a8a74df1SFan Wu static bool evaluate_boot_verified(const struct ipe_eval_ctx *const ctx) 63a8a74df1SFan Wu { 64a8a74df1SFan Wu return ctx->initramfs; 6552443cb6SDeven Bowers } 6652443cb6SDeven Bowers 6752443cb6SDeven Bowers /** 6805a35163SDeven Bowers * evaluate_property() - Analyze @ctx against a rule property. 6905a35163SDeven Bowers * @ctx: Supplies a pointer to the context to be evaluated. 7005a35163SDeven Bowers * @p: Supplies a pointer to the property to be evaluated. 7105a35163SDeven Bowers * 72a8a74df1SFan Wu * This function Determines whether the specified @ctx 73a8a74df1SFan Wu * matches the conditions defined by a rule property @p. 7405a35163SDeven Bowers * 7505a35163SDeven Bowers * Return: 7605a35163SDeven Bowers * * %true - The current @ctx match the @p 7705a35163SDeven Bowers * * %false - The current @ctx doesn't match the @p 7805a35163SDeven Bowers */ 7905a35163SDeven Bowers static bool evaluate_property(const struct ipe_eval_ctx *const ctx, 8005a35163SDeven Bowers struct ipe_prop *p) 8105a35163SDeven Bowers { 82a8a74df1SFan Wu switch (p->type) { 83a8a74df1SFan Wu case IPE_PROP_BOOT_VERIFIED_FALSE: 84a8a74df1SFan Wu return !evaluate_boot_verified(ctx); 85a8a74df1SFan Wu case IPE_PROP_BOOT_VERIFIED_TRUE: 86a8a74df1SFan Wu return evaluate_boot_verified(ctx); 87a8a74df1SFan Wu default: 8805a35163SDeven Bowers return false; 8905a35163SDeven Bowers } 90a8a74df1SFan Wu } 9105a35163SDeven Bowers 9205a35163SDeven Bowers /** 9305a35163SDeven Bowers * ipe_evaluate_event() - Analyze @ctx against the current active policy. 9405a35163SDeven Bowers * @ctx: Supplies a pointer to the context to be evaluated. 9505a35163SDeven Bowers * 9605a35163SDeven Bowers * This is the loop where all policy evaluations happen against the IPE policy. 9705a35163SDeven Bowers * 9805a35163SDeven Bowers * Return: 9905a35163SDeven Bowers * * %0 - Success 10005a35163SDeven Bowers * * %-EACCES - @ctx did not pass evaluation 10105a35163SDeven Bowers */ 10205a35163SDeven Bowers int ipe_evaluate_event(const struct ipe_eval_ctx *const ctx) 10305a35163SDeven Bowers { 10405a35163SDeven Bowers const struct ipe_op_table *rules = NULL; 10505a35163SDeven Bowers const struct ipe_rule *rule = NULL; 10605a35163SDeven Bowers struct ipe_policy *pol = NULL; 10705a35163SDeven Bowers struct ipe_prop *prop = NULL; 10805a35163SDeven Bowers enum ipe_action_type action; 109*f44554b5SDeven Bowers enum ipe_match match_type; 11005a35163SDeven Bowers bool match = false; 11105a35163SDeven Bowers 11205a35163SDeven Bowers rcu_read_lock(); 11305a35163SDeven Bowers 11405a35163SDeven Bowers pol = rcu_dereference(ipe_active_policy); 11505a35163SDeven Bowers if (!pol) { 11605a35163SDeven Bowers rcu_read_unlock(); 11705a35163SDeven Bowers return 0; 11805a35163SDeven Bowers } 11905a35163SDeven Bowers 12005a35163SDeven Bowers if (ctx->op == IPE_OP_INVALID) { 121*f44554b5SDeven Bowers if (pol->parsed->global_default_action == IPE_ACTION_INVALID) { 12205a35163SDeven Bowers WARN(1, "no default rule set for unknown op, ALLOW it"); 123*f44554b5SDeven Bowers action = IPE_ACTION_ALLOW; 124*f44554b5SDeven Bowers } else { 125*f44554b5SDeven Bowers action = pol->parsed->global_default_action; 126*f44554b5SDeven Bowers } 127*f44554b5SDeven Bowers match_type = IPE_MATCH_GLOBAL; 128*f44554b5SDeven Bowers goto eval; 12905a35163SDeven Bowers } 13005a35163SDeven Bowers 13105a35163SDeven Bowers rules = &pol->parsed->rules[ctx->op]; 13205a35163SDeven Bowers 13305a35163SDeven Bowers list_for_each_entry(rule, &rules->rules, next) { 13405a35163SDeven Bowers match = true; 13505a35163SDeven Bowers 13605a35163SDeven Bowers list_for_each_entry(prop, &rule->props, next) { 13705a35163SDeven Bowers match = evaluate_property(ctx, prop); 13805a35163SDeven Bowers if (!match) 13905a35163SDeven Bowers break; 14005a35163SDeven Bowers } 14105a35163SDeven Bowers 14205a35163SDeven Bowers if (match) 14305a35163SDeven Bowers break; 14405a35163SDeven Bowers } 14505a35163SDeven Bowers 146*f44554b5SDeven Bowers if (match) { 14705a35163SDeven Bowers action = rule->action; 148*f44554b5SDeven Bowers match_type = IPE_MATCH_RULE; 149*f44554b5SDeven Bowers } else if (rules->default_action != IPE_ACTION_INVALID) { 15005a35163SDeven Bowers action = rules->default_action; 151*f44554b5SDeven Bowers match_type = IPE_MATCH_TABLE; 152*f44554b5SDeven Bowers } else { 15305a35163SDeven Bowers action = pol->parsed->global_default_action; 154*f44554b5SDeven Bowers match_type = IPE_MATCH_GLOBAL; 155*f44554b5SDeven Bowers } 15605a35163SDeven Bowers 157*f44554b5SDeven Bowers eval: 158*f44554b5SDeven Bowers ipe_audit_match(ctx, match_type, action, rule); 15905a35163SDeven Bowers rcu_read_unlock(); 160*f44554b5SDeven Bowers 16105a35163SDeven Bowers if (action == IPE_ACTION_DENY) 16205a35163SDeven Bowers return -EACCES; 16305a35163SDeven Bowers 16405a35163SDeven Bowers return 0; 16505a35163SDeven Bowers } 166*f44554b5SDeven Bowers 167*f44554b5SDeven Bowers /* Set the right module name */ 168*f44554b5SDeven Bowers #ifdef KBUILD_MODNAME 169*f44554b5SDeven Bowers #undef KBUILD_MODNAME 170*f44554b5SDeven Bowers #define KBUILD_MODNAME "ipe" 171*f44554b5SDeven Bowers #endif 172*f44554b5SDeven Bowers 173*f44554b5SDeven Bowers module_param(success_audit, bool, 0400); 174*f44554b5SDeven Bowers MODULE_PARM_DESC(success_audit, "Start IPE with success auditing enabled"); 175