xref: /linux/security/ipe/eval.c (revision 52443cb60c356707df494910fa134bbb0a8b1a66)
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>
1205a35163SDeven Bowers 
1305a35163SDeven Bowers #include "ipe.h"
1405a35163SDeven Bowers #include "eval.h"
1505a35163SDeven Bowers #include "policy.h"
1605a35163SDeven Bowers 
1705a35163SDeven Bowers struct ipe_policy __rcu *ipe_active_policy;
1805a35163SDeven Bowers 
1905a35163SDeven Bowers /**
20*52443cb6SDeven Bowers  * ipe_build_eval_ctx() - Build an ipe evaluation context.
21*52443cb6SDeven Bowers  * @ctx: Supplies a pointer to the context to be populated.
22*52443cb6SDeven Bowers  * @file: Supplies a pointer to the file to associated with the evaluation.
23*52443cb6SDeven Bowers  * @op: Supplies the IPE policy operation associated with the evaluation.
24*52443cb6SDeven Bowers  */
25*52443cb6SDeven Bowers void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx,
26*52443cb6SDeven Bowers 			const struct file *file,
27*52443cb6SDeven Bowers 			enum ipe_op_type op)
28*52443cb6SDeven Bowers {
29*52443cb6SDeven Bowers 	ctx->file = file;
30*52443cb6SDeven Bowers 	ctx->op = op;
31*52443cb6SDeven Bowers }
32*52443cb6SDeven Bowers 
33*52443cb6SDeven Bowers /**
3405a35163SDeven Bowers  * evaluate_property() - Analyze @ctx against a rule property.
3505a35163SDeven Bowers  * @ctx: Supplies a pointer to the context to be evaluated.
3605a35163SDeven Bowers  * @p: Supplies a pointer to the property to be evaluated.
3705a35163SDeven Bowers  *
3805a35163SDeven Bowers  * This is a placeholder. The actual function will be introduced in the
3905a35163SDeven Bowers  * latter commits.
4005a35163SDeven Bowers  *
4105a35163SDeven Bowers  * Return:
4205a35163SDeven Bowers  * * %true	- The current @ctx match the @p
4305a35163SDeven Bowers  * * %false	- The current @ctx doesn't match the @p
4405a35163SDeven Bowers  */
4505a35163SDeven Bowers static bool evaluate_property(const struct ipe_eval_ctx *const ctx,
4605a35163SDeven Bowers 			      struct ipe_prop *p)
4705a35163SDeven Bowers {
4805a35163SDeven Bowers 	return false;
4905a35163SDeven Bowers }
5005a35163SDeven Bowers 
5105a35163SDeven Bowers /**
5205a35163SDeven Bowers  * ipe_evaluate_event() - Analyze @ctx against the current active policy.
5305a35163SDeven Bowers  * @ctx: Supplies a pointer to the context to be evaluated.
5405a35163SDeven Bowers  *
5505a35163SDeven Bowers  * This is the loop where all policy evaluations happen against the IPE policy.
5605a35163SDeven Bowers  *
5705a35163SDeven Bowers  * Return:
5805a35163SDeven Bowers  * * %0		- Success
5905a35163SDeven Bowers  * * %-EACCES	- @ctx did not pass evaluation
6005a35163SDeven Bowers  */
6105a35163SDeven Bowers int ipe_evaluate_event(const struct ipe_eval_ctx *const ctx)
6205a35163SDeven Bowers {
6305a35163SDeven Bowers 	const struct ipe_op_table *rules = NULL;
6405a35163SDeven Bowers 	const struct ipe_rule *rule = NULL;
6505a35163SDeven Bowers 	struct ipe_policy *pol = NULL;
6605a35163SDeven Bowers 	struct ipe_prop *prop = NULL;
6705a35163SDeven Bowers 	enum ipe_action_type action;
6805a35163SDeven Bowers 	bool match = false;
6905a35163SDeven Bowers 
7005a35163SDeven Bowers 	rcu_read_lock();
7105a35163SDeven Bowers 
7205a35163SDeven Bowers 	pol = rcu_dereference(ipe_active_policy);
7305a35163SDeven Bowers 	if (!pol) {
7405a35163SDeven Bowers 		rcu_read_unlock();
7505a35163SDeven Bowers 		return 0;
7605a35163SDeven Bowers 	}
7705a35163SDeven Bowers 
7805a35163SDeven Bowers 	if (ctx->op == IPE_OP_INVALID) {
7905a35163SDeven Bowers 		if (pol->parsed->global_default_action == IPE_ACTION_DENY) {
8005a35163SDeven Bowers 			rcu_read_unlock();
8105a35163SDeven Bowers 			return -EACCES;
8205a35163SDeven Bowers 		}
8305a35163SDeven Bowers 		if (pol->parsed->global_default_action == IPE_ACTION_INVALID)
8405a35163SDeven Bowers 			WARN(1, "no default rule set for unknown op, ALLOW it");
8505a35163SDeven Bowers 		rcu_read_unlock();
8605a35163SDeven Bowers 		return 0;
8705a35163SDeven Bowers 	}
8805a35163SDeven Bowers 
8905a35163SDeven Bowers 	rules = &pol->parsed->rules[ctx->op];
9005a35163SDeven Bowers 
9105a35163SDeven Bowers 	list_for_each_entry(rule, &rules->rules, next) {
9205a35163SDeven Bowers 		match = true;
9305a35163SDeven Bowers 
9405a35163SDeven Bowers 		list_for_each_entry(prop, &rule->props, next) {
9505a35163SDeven Bowers 			match = evaluate_property(ctx, prop);
9605a35163SDeven Bowers 			if (!match)
9705a35163SDeven Bowers 				break;
9805a35163SDeven Bowers 		}
9905a35163SDeven Bowers 
10005a35163SDeven Bowers 		if (match)
10105a35163SDeven Bowers 			break;
10205a35163SDeven Bowers 	}
10305a35163SDeven Bowers 
10405a35163SDeven Bowers 	if (match)
10505a35163SDeven Bowers 		action = rule->action;
10605a35163SDeven Bowers 	else if (rules->default_action != IPE_ACTION_INVALID)
10705a35163SDeven Bowers 		action = rules->default_action;
10805a35163SDeven Bowers 	else
10905a35163SDeven Bowers 		action = pol->parsed->global_default_action;
11005a35163SDeven Bowers 
11105a35163SDeven Bowers 	rcu_read_unlock();
11205a35163SDeven Bowers 	if (action == IPE_ACTION_DENY)
11305a35163SDeven Bowers 		return -EACCES;
11405a35163SDeven Bowers 
11505a35163SDeven Bowers 	return 0;
11605a35163SDeven Bowers }
117