1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved. 4 */ 5 6 #include <linux/fs.h> 7 #include <linux/types.h> 8 #include <linux/slab.h> 9 #include <linux/file.h> 10 #include <linux/sched.h> 11 #include <linux/rcupdate.h> 12 13 #include "ipe.h" 14 #include "eval.h" 15 #include "policy.h" 16 17 struct ipe_policy __rcu *ipe_active_policy; 18 19 #define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb) 20 21 /** 22 * build_ipe_sb_ctx() - Build initramfs field of an ipe evaluation context. 23 * @ctx: Supplies a pointer to the context to be populated. 24 * @file: Supplies the file struct of the file triggered IPE event. 25 */ 26 static void build_ipe_sb_ctx(struct ipe_eval_ctx *ctx, const struct file *const file) 27 { 28 ctx->initramfs = ipe_sb(FILE_SUPERBLOCK(file))->initramfs; 29 } 30 31 /** 32 * ipe_build_eval_ctx() - Build an ipe evaluation context. 33 * @ctx: Supplies a pointer to the context to be populated. 34 * @file: Supplies a pointer to the file to associated with the evaluation. 35 * @op: Supplies the IPE policy operation associated with the evaluation. 36 */ 37 void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx, 38 const struct file *file, 39 enum ipe_op_type op) 40 { 41 ctx->file = file; 42 ctx->op = op; 43 44 if (file) 45 build_ipe_sb_ctx(ctx, file); 46 } 47 48 /** 49 * evaluate_boot_verified() - Evaluate @ctx for the boot verified property. 50 * @ctx: Supplies a pointer to the context being evaluated. 51 * 52 * Return: 53 * * %true - The current @ctx match the @p 54 * * %false - The current @ctx doesn't match the @p 55 */ 56 static bool evaluate_boot_verified(const struct ipe_eval_ctx *const ctx) 57 { 58 return ctx->initramfs; 59 } 60 61 /** 62 * evaluate_property() - Analyze @ctx against a rule property. 63 * @ctx: Supplies a pointer to the context to be evaluated. 64 * @p: Supplies a pointer to the property to be evaluated. 65 * 66 * This function Determines whether the specified @ctx 67 * matches the conditions defined by a rule property @p. 68 * 69 * Return: 70 * * %true - The current @ctx match the @p 71 * * %false - The current @ctx doesn't match the @p 72 */ 73 static bool evaluate_property(const struct ipe_eval_ctx *const ctx, 74 struct ipe_prop *p) 75 { 76 switch (p->type) { 77 case IPE_PROP_BOOT_VERIFIED_FALSE: 78 return !evaluate_boot_verified(ctx); 79 case IPE_PROP_BOOT_VERIFIED_TRUE: 80 return evaluate_boot_verified(ctx); 81 default: 82 return false; 83 } 84 } 85 86 /** 87 * ipe_evaluate_event() - Analyze @ctx against the current active policy. 88 * @ctx: Supplies a pointer to the context to be evaluated. 89 * 90 * This is the loop where all policy evaluations happen against the IPE policy. 91 * 92 * Return: 93 * * %0 - Success 94 * * %-EACCES - @ctx did not pass evaluation 95 */ 96 int ipe_evaluate_event(const struct ipe_eval_ctx *const ctx) 97 { 98 const struct ipe_op_table *rules = NULL; 99 const struct ipe_rule *rule = NULL; 100 struct ipe_policy *pol = NULL; 101 struct ipe_prop *prop = NULL; 102 enum ipe_action_type action; 103 bool match = false; 104 105 rcu_read_lock(); 106 107 pol = rcu_dereference(ipe_active_policy); 108 if (!pol) { 109 rcu_read_unlock(); 110 return 0; 111 } 112 113 if (ctx->op == IPE_OP_INVALID) { 114 if (pol->parsed->global_default_action == IPE_ACTION_DENY) { 115 rcu_read_unlock(); 116 return -EACCES; 117 } 118 if (pol->parsed->global_default_action == IPE_ACTION_INVALID) 119 WARN(1, "no default rule set for unknown op, ALLOW it"); 120 rcu_read_unlock(); 121 return 0; 122 } 123 124 rules = &pol->parsed->rules[ctx->op]; 125 126 list_for_each_entry(rule, &rules->rules, next) { 127 match = true; 128 129 list_for_each_entry(prop, &rule->props, next) { 130 match = evaluate_property(ctx, prop); 131 if (!match) 132 break; 133 } 134 135 if (match) 136 break; 137 } 138 139 if (match) 140 action = rule->action; 141 else if (rules->default_action != IPE_ACTION_INVALID) 142 action = rules->default_action; 143 else 144 action = pol->parsed->global_default_action; 145 146 rcu_read_unlock(); 147 if (action == IPE_ACTION_DENY) 148 return -EACCES; 149 150 return 0; 151 } 152