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> 12f44554b5SDeven Bowers #include <linux/moduleparam.h> 1305a35163SDeven Bowers 1405a35163SDeven Bowers #include "ipe.h" 1505a35163SDeven Bowers #include "eval.h" 1605a35163SDeven Bowers #include "policy.h" 17f44554b5SDeven Bowers #include "audit.h" 1805a35163SDeven Bowers 1905a35163SDeven Bowers struct ipe_policy __rcu *ipe_active_policy; 20f44554b5SDeven Bowers bool success_audit; 21*a68916eaSDeven Bowers bool enforce = true; 2205a35163SDeven Bowers 23a8a74df1SFan Wu #define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb) 24a8a74df1SFan Wu 25a8a74df1SFan Wu /** 26a8a74df1SFan Wu * build_ipe_sb_ctx() - Build initramfs field of an ipe evaluation context. 27a8a74df1SFan Wu * @ctx: Supplies a pointer to the context to be populated. 28a8a74df1SFan Wu * @file: Supplies the file struct of the file triggered IPE event. 29a8a74df1SFan Wu */ 30a8a74df1SFan Wu static void build_ipe_sb_ctx(struct ipe_eval_ctx *ctx, const struct file *const file) 31a8a74df1SFan Wu { 32a8a74df1SFan Wu ctx->initramfs = ipe_sb(FILE_SUPERBLOCK(file))->initramfs; 33a8a74df1SFan Wu } 34a8a74df1SFan Wu 3505a35163SDeven Bowers /** 3652443cb6SDeven Bowers * ipe_build_eval_ctx() - Build an ipe evaluation context. 3752443cb6SDeven Bowers * @ctx: Supplies a pointer to the context to be populated. 3852443cb6SDeven Bowers * @file: Supplies a pointer to the file to associated with the evaluation. 3952443cb6SDeven Bowers * @op: Supplies the IPE policy operation associated with the evaluation. 40f44554b5SDeven Bowers * @hook: Supplies the LSM hook associated with the evaluation. 4152443cb6SDeven Bowers */ 4252443cb6SDeven Bowers void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx, 4352443cb6SDeven Bowers const struct file *file, 44f44554b5SDeven Bowers enum ipe_op_type op, 45f44554b5SDeven Bowers enum ipe_hook_type hook) 4652443cb6SDeven Bowers { 4752443cb6SDeven Bowers ctx->file = file; 4852443cb6SDeven Bowers ctx->op = op; 49f44554b5SDeven Bowers ctx->hook = hook; 50a8a74df1SFan Wu 51a8a74df1SFan Wu if (file) 52a8a74df1SFan Wu build_ipe_sb_ctx(ctx, file); 53a8a74df1SFan Wu } 54a8a74df1SFan Wu 55a8a74df1SFan Wu /** 56a8a74df1SFan Wu * evaluate_boot_verified() - Evaluate @ctx for the boot verified property. 57a8a74df1SFan Wu * @ctx: Supplies a pointer to the context being evaluated. 58a8a74df1SFan Wu * 59a8a74df1SFan Wu * Return: 60a8a74df1SFan Wu * * %true - The current @ctx match the @p 61a8a74df1SFan Wu * * %false - The current @ctx doesn't match the @p 62a8a74df1SFan Wu */ 63a8a74df1SFan Wu static bool evaluate_boot_verified(const struct ipe_eval_ctx *const ctx) 64a8a74df1SFan Wu { 65a8a74df1SFan Wu return ctx->initramfs; 6652443cb6SDeven Bowers } 6752443cb6SDeven Bowers 6852443cb6SDeven Bowers /** 6905a35163SDeven Bowers * evaluate_property() - Analyze @ctx against a rule property. 7005a35163SDeven Bowers * @ctx: Supplies a pointer to the context to be evaluated. 7105a35163SDeven Bowers * @p: Supplies a pointer to the property to be evaluated. 7205a35163SDeven Bowers * 73a8a74df1SFan Wu * This function Determines whether the specified @ctx 74a8a74df1SFan Wu * matches the conditions defined by a rule property @p. 7505a35163SDeven Bowers * 7605a35163SDeven Bowers * Return: 7705a35163SDeven Bowers * * %true - The current @ctx match the @p 7805a35163SDeven Bowers * * %false - The current @ctx doesn't match the @p 7905a35163SDeven Bowers */ 8005a35163SDeven Bowers static bool evaluate_property(const struct ipe_eval_ctx *const ctx, 8105a35163SDeven Bowers struct ipe_prop *p) 8205a35163SDeven Bowers { 83a8a74df1SFan Wu switch (p->type) { 84a8a74df1SFan Wu case IPE_PROP_BOOT_VERIFIED_FALSE: 85a8a74df1SFan Wu return !evaluate_boot_verified(ctx); 86a8a74df1SFan Wu case IPE_PROP_BOOT_VERIFIED_TRUE: 87a8a74df1SFan Wu return evaluate_boot_verified(ctx); 88a8a74df1SFan Wu default: 8905a35163SDeven Bowers return false; 9005a35163SDeven Bowers } 91a8a74df1SFan Wu } 9205a35163SDeven Bowers 9305a35163SDeven Bowers /** 9405a35163SDeven Bowers * ipe_evaluate_event() - Analyze @ctx against the current active policy. 9505a35163SDeven Bowers * @ctx: Supplies a pointer to the context to be evaluated. 9605a35163SDeven Bowers * 9705a35163SDeven Bowers * This is the loop where all policy evaluations happen against the IPE policy. 9805a35163SDeven Bowers * 9905a35163SDeven Bowers * Return: 10005a35163SDeven Bowers * * %0 - Success 10105a35163SDeven Bowers * * %-EACCES - @ctx did not pass evaluation 10205a35163SDeven Bowers */ 10305a35163SDeven Bowers int ipe_evaluate_event(const struct ipe_eval_ctx *const ctx) 10405a35163SDeven Bowers { 10505a35163SDeven Bowers const struct ipe_op_table *rules = NULL; 10605a35163SDeven Bowers const struct ipe_rule *rule = NULL; 10705a35163SDeven Bowers struct ipe_policy *pol = NULL; 10805a35163SDeven Bowers struct ipe_prop *prop = NULL; 10905a35163SDeven Bowers enum ipe_action_type action; 110f44554b5SDeven Bowers enum ipe_match match_type; 11105a35163SDeven Bowers bool match = false; 112*a68916eaSDeven Bowers int rc = 0; 11305a35163SDeven Bowers 11405a35163SDeven Bowers rcu_read_lock(); 11505a35163SDeven Bowers 11605a35163SDeven Bowers pol = rcu_dereference(ipe_active_policy); 11705a35163SDeven Bowers if (!pol) { 11805a35163SDeven Bowers rcu_read_unlock(); 11905a35163SDeven Bowers return 0; 12005a35163SDeven Bowers } 12105a35163SDeven Bowers 12205a35163SDeven Bowers if (ctx->op == IPE_OP_INVALID) { 123f44554b5SDeven Bowers if (pol->parsed->global_default_action == IPE_ACTION_INVALID) { 12405a35163SDeven Bowers WARN(1, "no default rule set for unknown op, ALLOW it"); 125f44554b5SDeven Bowers action = IPE_ACTION_ALLOW; 126f44554b5SDeven Bowers } else { 127f44554b5SDeven Bowers action = pol->parsed->global_default_action; 128f44554b5SDeven Bowers } 129f44554b5SDeven Bowers match_type = IPE_MATCH_GLOBAL; 130f44554b5SDeven Bowers goto eval; 13105a35163SDeven Bowers } 13205a35163SDeven Bowers 13305a35163SDeven Bowers rules = &pol->parsed->rules[ctx->op]; 13405a35163SDeven Bowers 13505a35163SDeven Bowers list_for_each_entry(rule, &rules->rules, next) { 13605a35163SDeven Bowers match = true; 13705a35163SDeven Bowers 13805a35163SDeven Bowers list_for_each_entry(prop, &rule->props, next) { 13905a35163SDeven Bowers match = evaluate_property(ctx, prop); 14005a35163SDeven Bowers if (!match) 14105a35163SDeven Bowers break; 14205a35163SDeven Bowers } 14305a35163SDeven Bowers 14405a35163SDeven Bowers if (match) 14505a35163SDeven Bowers break; 14605a35163SDeven Bowers } 14705a35163SDeven Bowers 148f44554b5SDeven Bowers if (match) { 14905a35163SDeven Bowers action = rule->action; 150f44554b5SDeven Bowers match_type = IPE_MATCH_RULE; 151f44554b5SDeven Bowers } else if (rules->default_action != IPE_ACTION_INVALID) { 15205a35163SDeven Bowers action = rules->default_action; 153f44554b5SDeven Bowers match_type = IPE_MATCH_TABLE; 154f44554b5SDeven Bowers } else { 15505a35163SDeven Bowers action = pol->parsed->global_default_action; 156f44554b5SDeven Bowers match_type = IPE_MATCH_GLOBAL; 157f44554b5SDeven Bowers } 15805a35163SDeven Bowers 159f44554b5SDeven Bowers eval: 160f44554b5SDeven Bowers ipe_audit_match(ctx, match_type, action, rule); 16105a35163SDeven Bowers rcu_read_unlock(); 162f44554b5SDeven Bowers 16305a35163SDeven Bowers if (action == IPE_ACTION_DENY) 164*a68916eaSDeven Bowers rc = -EACCES; 16505a35163SDeven Bowers 166*a68916eaSDeven Bowers if (!READ_ONCE(enforce)) 167*a68916eaSDeven Bowers rc = 0; 168*a68916eaSDeven Bowers 169*a68916eaSDeven Bowers return rc; 17005a35163SDeven Bowers } 171f44554b5SDeven Bowers 172f44554b5SDeven Bowers /* Set the right module name */ 173f44554b5SDeven Bowers #ifdef KBUILD_MODNAME 174f44554b5SDeven Bowers #undef KBUILD_MODNAME 175f44554b5SDeven Bowers #define KBUILD_MODNAME "ipe" 176f44554b5SDeven Bowers #endif 177f44554b5SDeven Bowers 178f44554b5SDeven Bowers module_param(success_audit, bool, 0400); 179f44554b5SDeven Bowers MODULE_PARM_DESC(success_audit, "Start IPE with success auditing enabled"); 180*a68916eaSDeven Bowers module_param(enforce, bool, 0400); 181*a68916eaSDeven Bowers MODULE_PARM_DESC(enforce, "Start IPE in enforce or permissive mode"); 182