xref: /linux/security/ipe/eval.c (revision f44554b5067b36c14cc91ed811fa1bd58baed34a)
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