xref: /linux/security/ipe/eval.c (revision a430d95c5efa2b545d26a094eb5f624e36732af0)
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>
13*31f8c868SFan Wu #include <linux/fsverity.h>
1405a35163SDeven Bowers 
1505a35163SDeven Bowers #include "ipe.h"
1605a35163SDeven Bowers #include "eval.h"
1705a35163SDeven Bowers #include "policy.h"
18f44554b5SDeven Bowers #include "audit.h"
19e155858dSDeven Bowers #include "digest.h"
2005a35163SDeven Bowers 
2105a35163SDeven Bowers struct ipe_policy __rcu *ipe_active_policy;
22f44554b5SDeven Bowers bool success_audit;
23a68916eaSDeven Bowers bool enforce = true;
24e155858dSDeven Bowers #define INO_BLOCK_DEV(ino) ((ino)->i_sb->s_bdev)
2505a35163SDeven Bowers 
26a8a74df1SFan Wu #define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb)
27a8a74df1SFan Wu 
28a8a74df1SFan Wu /**
29a8a74df1SFan Wu  * build_ipe_sb_ctx() - Build initramfs field of an ipe evaluation context.
30a8a74df1SFan Wu  * @ctx: Supplies a pointer to the context to be populated.
31a8a74df1SFan Wu  * @file: Supplies the file struct of the file triggered IPE event.
32a8a74df1SFan Wu  */
build_ipe_sb_ctx(struct ipe_eval_ctx * ctx,const struct file * const file)33a8a74df1SFan Wu static void build_ipe_sb_ctx(struct ipe_eval_ctx *ctx, const struct file *const file)
34a8a74df1SFan Wu {
35a8a74df1SFan Wu 	ctx->initramfs = ipe_sb(FILE_SUPERBLOCK(file))->initramfs;
36a8a74df1SFan Wu }
37a8a74df1SFan Wu 
38e155858dSDeven Bowers #ifdef CONFIG_IPE_PROP_DM_VERITY
39e155858dSDeven Bowers /**
40e155858dSDeven Bowers  * build_ipe_bdev_ctx() - Build ipe_bdev field of an evaluation context.
41e155858dSDeven Bowers  * @ctx: Supplies a pointer to the context to be populated.
42e155858dSDeven Bowers  * @ino: Supplies the inode struct of the file triggered IPE event.
43e155858dSDeven Bowers  */
build_ipe_bdev_ctx(struct ipe_eval_ctx * ctx,const struct inode * const ino)44e155858dSDeven Bowers static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
45e155858dSDeven Bowers {
46e155858dSDeven Bowers 	if (INO_BLOCK_DEV(ino))
47e155858dSDeven Bowers 		ctx->ipe_bdev = ipe_bdev(INO_BLOCK_DEV(ino));
48e155858dSDeven Bowers }
49e155858dSDeven Bowers #else
build_ipe_bdev_ctx(struct ipe_eval_ctx * ctx,const struct inode * const ino)50e155858dSDeven Bowers static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
51e155858dSDeven Bowers {
52e155858dSDeven Bowers }
53e155858dSDeven Bowers #endif /* CONFIG_IPE_PROP_DM_VERITY */
54e155858dSDeven Bowers 
55*31f8c868SFan Wu #ifdef CONFIG_IPE_PROP_FS_VERITY
56*31f8c868SFan Wu #ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
build_ipe_inode_blob_ctx(struct ipe_eval_ctx * ctx,const struct inode * const ino)57*31f8c868SFan Wu static void build_ipe_inode_blob_ctx(struct ipe_eval_ctx *ctx,
58*31f8c868SFan Wu 				     const struct inode *const ino)
59*31f8c868SFan Wu {
60*31f8c868SFan Wu 	ctx->ipe_inode = ipe_inode(ctx->ino);
61*31f8c868SFan Wu }
62*31f8c868SFan Wu #else
build_ipe_inode_blob_ctx(struct ipe_eval_ctx * ctx,const struct inode * const ino)63*31f8c868SFan Wu static inline void build_ipe_inode_blob_ctx(struct ipe_eval_ctx *ctx,
64*31f8c868SFan Wu 					    const struct inode *const ino)
65*31f8c868SFan Wu {
66*31f8c868SFan Wu }
67*31f8c868SFan Wu #endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
68*31f8c868SFan Wu 
69*31f8c868SFan Wu /**
70*31f8c868SFan Wu  * build_ipe_inode_ctx() - Build inode fields of an evaluation context.
71*31f8c868SFan Wu  * @ctx: Supplies a pointer to the context to be populated.
72*31f8c868SFan Wu  * @ino: Supplies the inode struct of the file triggered IPE event.
73*31f8c868SFan Wu  */
build_ipe_inode_ctx(struct ipe_eval_ctx * ctx,const struct inode * const ino)74*31f8c868SFan Wu static void build_ipe_inode_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
75*31f8c868SFan Wu {
76*31f8c868SFan Wu 	ctx->ino = ino;
77*31f8c868SFan Wu 	build_ipe_inode_blob_ctx(ctx, ino);
78*31f8c868SFan Wu }
79*31f8c868SFan Wu #else
build_ipe_inode_ctx(struct ipe_eval_ctx * ctx,const struct inode * const ino)80*31f8c868SFan Wu static void build_ipe_inode_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
81*31f8c868SFan Wu {
82*31f8c868SFan Wu }
83*31f8c868SFan Wu #endif /* CONFIG_IPE_PROP_FS_VERITY */
84*31f8c868SFan Wu 
8505a35163SDeven Bowers /**
8652443cb6SDeven Bowers  * ipe_build_eval_ctx() - Build an ipe evaluation context.
8752443cb6SDeven Bowers  * @ctx: Supplies a pointer to the context to be populated.
8852443cb6SDeven Bowers  * @file: Supplies a pointer to the file to associated with the evaluation.
8952443cb6SDeven Bowers  * @op: Supplies the IPE policy operation associated with the evaluation.
90f44554b5SDeven Bowers  * @hook: Supplies the LSM hook associated with the evaluation.
9152443cb6SDeven Bowers  */
ipe_build_eval_ctx(struct ipe_eval_ctx * ctx,const struct file * file,enum ipe_op_type op,enum ipe_hook_type hook)9252443cb6SDeven Bowers void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx,
9352443cb6SDeven Bowers 			const struct file *file,
94f44554b5SDeven Bowers 			enum ipe_op_type op,
95f44554b5SDeven Bowers 			enum ipe_hook_type hook)
9652443cb6SDeven Bowers {
97*31f8c868SFan Wu 	struct inode *ino;
98*31f8c868SFan Wu 
9952443cb6SDeven Bowers 	ctx->file = file;
10052443cb6SDeven Bowers 	ctx->op = op;
101f44554b5SDeven Bowers 	ctx->hook = hook;
102a8a74df1SFan Wu 
103e155858dSDeven Bowers 	if (file) {
104a8a74df1SFan Wu 		build_ipe_sb_ctx(ctx, file);
105*31f8c868SFan Wu 		ino = d_real_inode(file->f_path.dentry);
106*31f8c868SFan Wu 		build_ipe_bdev_ctx(ctx, ino);
107*31f8c868SFan Wu 		build_ipe_inode_ctx(ctx, ino);
108e155858dSDeven Bowers 	}
109a8a74df1SFan Wu }
110a8a74df1SFan Wu 
111a8a74df1SFan Wu /**
112a8a74df1SFan Wu  * evaluate_boot_verified() - Evaluate @ctx for the boot verified property.
113a8a74df1SFan Wu  * @ctx: Supplies a pointer to the context being evaluated.
114a8a74df1SFan Wu  *
115a8a74df1SFan Wu  * Return:
116a8a74df1SFan Wu  * * %true	- The current @ctx match the @p
117a8a74df1SFan Wu  * * %false	- The current @ctx doesn't match the @p
118a8a74df1SFan Wu  */
evaluate_boot_verified(const struct ipe_eval_ctx * const ctx)119a8a74df1SFan Wu static bool evaluate_boot_verified(const struct ipe_eval_ctx *const ctx)
120a8a74df1SFan Wu {
121a8a74df1SFan Wu 	return ctx->initramfs;
12252443cb6SDeven Bowers }
12352443cb6SDeven Bowers 
124e155858dSDeven Bowers #ifdef CONFIG_IPE_PROP_DM_VERITY
125e155858dSDeven Bowers /**
126e155858dSDeven Bowers  * evaluate_dmv_roothash() - Evaluate @ctx against a dmv roothash property.
127e155858dSDeven Bowers  * @ctx: Supplies a pointer to the context being evaluated.
128e155858dSDeven Bowers  * @p: Supplies a pointer to the property being evaluated.
129e155858dSDeven Bowers  *
130e155858dSDeven Bowers  * Return:
131e155858dSDeven Bowers  * * %true	- The current @ctx match the @p
132e155858dSDeven Bowers  * * %false	- The current @ctx doesn't match the @p
133e155858dSDeven Bowers  */
evaluate_dmv_roothash(const struct ipe_eval_ctx * const ctx,struct ipe_prop * p)134e155858dSDeven Bowers static bool evaluate_dmv_roothash(const struct ipe_eval_ctx *const ctx,
135e155858dSDeven Bowers 				  struct ipe_prop *p)
136e155858dSDeven Bowers {
137e155858dSDeven Bowers 	return !!ctx->ipe_bdev &&
138e155858dSDeven Bowers 	       !!ctx->ipe_bdev->root_hash &&
139e155858dSDeven Bowers 	       ipe_digest_eval(p->value,
140e155858dSDeven Bowers 			       ctx->ipe_bdev->root_hash);
141e155858dSDeven Bowers }
142e155858dSDeven Bowers #else
evaluate_dmv_roothash(const struct ipe_eval_ctx * const ctx,struct ipe_prop * p)143e155858dSDeven Bowers static bool evaluate_dmv_roothash(const struct ipe_eval_ctx *const ctx,
144e155858dSDeven Bowers 				  struct ipe_prop *p)
145e155858dSDeven Bowers {
146e155858dSDeven Bowers 	return false;
147e155858dSDeven Bowers }
148e155858dSDeven Bowers #endif /* CONFIG_IPE_PROP_DM_VERITY */
149e155858dSDeven Bowers 
150e155858dSDeven Bowers #ifdef CONFIG_IPE_PROP_DM_VERITY_SIGNATURE
151e155858dSDeven Bowers /**
152e155858dSDeven Bowers  * evaluate_dmv_sig_false() - Evaluate @ctx against a dmv sig false property.
153e155858dSDeven Bowers  * @ctx: Supplies a pointer to the context being evaluated.
154e155858dSDeven Bowers  *
155e155858dSDeven Bowers  * Return:
156e155858dSDeven Bowers  * * %true	- The current @ctx match the property
157e155858dSDeven Bowers  * * %false	- The current @ctx doesn't match the property
158e155858dSDeven Bowers  */
evaluate_dmv_sig_false(const struct ipe_eval_ctx * const ctx)159e155858dSDeven Bowers static bool evaluate_dmv_sig_false(const struct ipe_eval_ctx *const ctx)
160e155858dSDeven Bowers {
161e155858dSDeven Bowers 	return !ctx->ipe_bdev || (!ctx->ipe_bdev->dm_verity_signed);
162e155858dSDeven Bowers }
163e155858dSDeven Bowers 
164e155858dSDeven Bowers /**
165e155858dSDeven Bowers  * evaluate_dmv_sig_true() - Evaluate @ctx against a dmv sig true property.
166e155858dSDeven Bowers  * @ctx: Supplies a pointer to the context being evaluated.
167e155858dSDeven Bowers  *
168e155858dSDeven Bowers  * Return:
169e155858dSDeven Bowers  * * %true	- The current @ctx match the property
170e155858dSDeven Bowers  * * %false	- The current @ctx doesn't match the property
171e155858dSDeven Bowers  */
evaluate_dmv_sig_true(const struct ipe_eval_ctx * const ctx)172e155858dSDeven Bowers static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx *const ctx)
173e155858dSDeven Bowers {
174e155858dSDeven Bowers 	return !evaluate_dmv_sig_false(ctx);
175e155858dSDeven Bowers }
176e155858dSDeven Bowers #else
evaluate_dmv_sig_false(const struct ipe_eval_ctx * const ctx)177e155858dSDeven Bowers static bool evaluate_dmv_sig_false(const struct ipe_eval_ctx *const ctx)
178e155858dSDeven Bowers {
179e155858dSDeven Bowers 	return false;
180e155858dSDeven Bowers }
181e155858dSDeven Bowers 
evaluate_dmv_sig_true(const struct ipe_eval_ctx * const ctx)182e155858dSDeven Bowers static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx *const ctx)
183e155858dSDeven Bowers {
184e155858dSDeven Bowers 	return false;
185e155858dSDeven Bowers }
186e155858dSDeven Bowers #endif /* CONFIG_IPE_PROP_DM_VERITY_SIGNATURE */
187e155858dSDeven Bowers 
188*31f8c868SFan Wu #ifdef CONFIG_IPE_PROP_FS_VERITY
189*31f8c868SFan Wu /**
190*31f8c868SFan Wu  * evaluate_fsv_digest() - Evaluate @ctx against a fsv digest property.
191*31f8c868SFan Wu  * @ctx: Supplies a pointer to the context being evaluated.
192*31f8c868SFan Wu  * @p: Supplies a pointer to the property being evaluated.
193*31f8c868SFan Wu  *
194*31f8c868SFan Wu  * Return:
195*31f8c868SFan Wu  * * %true	- The current @ctx match the @p
196*31f8c868SFan Wu  * * %false	- The current @ctx doesn't match the @p
197*31f8c868SFan Wu  */
evaluate_fsv_digest(const struct ipe_eval_ctx * const ctx,struct ipe_prop * p)198*31f8c868SFan Wu static bool evaluate_fsv_digest(const struct ipe_eval_ctx *const ctx,
199*31f8c868SFan Wu 				struct ipe_prop *p)
200*31f8c868SFan Wu {
201*31f8c868SFan Wu 	enum hash_algo alg;
202*31f8c868SFan Wu 	u8 digest[FS_VERITY_MAX_DIGEST_SIZE];
203*31f8c868SFan Wu 	struct digest_info info;
204*31f8c868SFan Wu 
205*31f8c868SFan Wu 	if (!ctx->ino)
206*31f8c868SFan Wu 		return false;
207*31f8c868SFan Wu 	if (!fsverity_get_digest((struct inode *)ctx->ino,
208*31f8c868SFan Wu 				 digest,
209*31f8c868SFan Wu 				 NULL,
210*31f8c868SFan Wu 				 &alg))
211*31f8c868SFan Wu 		return false;
212*31f8c868SFan Wu 
213*31f8c868SFan Wu 	info.alg = hash_algo_name[alg];
214*31f8c868SFan Wu 	info.digest = digest;
215*31f8c868SFan Wu 	info.digest_len = hash_digest_size[alg];
216*31f8c868SFan Wu 
217*31f8c868SFan Wu 	return ipe_digest_eval(p->value, &info);
218*31f8c868SFan Wu }
219*31f8c868SFan Wu #else
evaluate_fsv_digest(const struct ipe_eval_ctx * const ctx,struct ipe_prop * p)220*31f8c868SFan Wu static bool evaluate_fsv_digest(const struct ipe_eval_ctx *const ctx,
221*31f8c868SFan Wu 				struct ipe_prop *p)
222*31f8c868SFan Wu {
223*31f8c868SFan Wu 	return false;
224*31f8c868SFan Wu }
225*31f8c868SFan Wu #endif /* CONFIG_IPE_PROP_FS_VERITY */
226*31f8c868SFan Wu 
227*31f8c868SFan Wu #ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
228*31f8c868SFan Wu /**
229*31f8c868SFan Wu  * evaluate_fsv_sig_false() - Evaluate @ctx against a fsv sig false property.
230*31f8c868SFan Wu  * @ctx: Supplies a pointer to the context being evaluated.
231*31f8c868SFan Wu  *
232*31f8c868SFan Wu  * Return:
233*31f8c868SFan Wu  * * %true	- The current @ctx match the property
234*31f8c868SFan Wu  * * %false	- The current @ctx doesn't match the property
235*31f8c868SFan Wu  */
evaluate_fsv_sig_false(const struct ipe_eval_ctx * const ctx)236*31f8c868SFan Wu static bool evaluate_fsv_sig_false(const struct ipe_eval_ctx *const ctx)
237*31f8c868SFan Wu {
238*31f8c868SFan Wu 	return !ctx->ino ||
239*31f8c868SFan Wu 	       !IS_VERITY(ctx->ino) ||
240*31f8c868SFan Wu 	       !ctx->ipe_inode ||
241*31f8c868SFan Wu 	       !ctx->ipe_inode->fs_verity_signed;
242*31f8c868SFan Wu }
243*31f8c868SFan Wu 
244*31f8c868SFan Wu /**
245*31f8c868SFan Wu  * evaluate_fsv_sig_true() - Evaluate @ctx against a fsv sig true property.
246*31f8c868SFan Wu  * @ctx: Supplies a pointer to the context being evaluated.
247*31f8c868SFan Wu  *
248*31f8c868SFan Wu  * Return:
249*31f8c868SFan Wu  * * %true - The current @ctx match the property
250*31f8c868SFan Wu  * * %false - The current @ctx doesn't match the property
251*31f8c868SFan Wu  */
evaluate_fsv_sig_true(const struct ipe_eval_ctx * const ctx)252*31f8c868SFan Wu static bool evaluate_fsv_sig_true(const struct ipe_eval_ctx *const ctx)
253*31f8c868SFan Wu {
254*31f8c868SFan Wu 	return !evaluate_fsv_sig_false(ctx);
255*31f8c868SFan Wu }
256*31f8c868SFan Wu #else
evaluate_fsv_sig_false(const struct ipe_eval_ctx * const ctx)257*31f8c868SFan Wu static bool evaluate_fsv_sig_false(const struct ipe_eval_ctx *const ctx)
258*31f8c868SFan Wu {
259*31f8c868SFan Wu 	return false;
260*31f8c868SFan Wu }
261*31f8c868SFan Wu 
evaluate_fsv_sig_true(const struct ipe_eval_ctx * const ctx)262*31f8c868SFan Wu static bool evaluate_fsv_sig_true(const struct ipe_eval_ctx *const ctx)
263*31f8c868SFan Wu {
264*31f8c868SFan Wu 	return false;
265*31f8c868SFan Wu }
266*31f8c868SFan Wu #endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
267*31f8c868SFan Wu 
26852443cb6SDeven Bowers /**
26905a35163SDeven Bowers  * evaluate_property() - Analyze @ctx against a rule property.
27005a35163SDeven Bowers  * @ctx: Supplies a pointer to the context to be evaluated.
27105a35163SDeven Bowers  * @p: Supplies a pointer to the property to be evaluated.
27205a35163SDeven Bowers  *
273a8a74df1SFan Wu  * This function Determines whether the specified @ctx
274a8a74df1SFan Wu  * matches the conditions defined by a rule property @p.
27505a35163SDeven Bowers  *
27605a35163SDeven Bowers  * Return:
27705a35163SDeven Bowers  * * %true	- The current @ctx match the @p
27805a35163SDeven Bowers  * * %false	- The current @ctx doesn't match the @p
27905a35163SDeven Bowers  */
evaluate_property(const struct ipe_eval_ctx * const ctx,struct ipe_prop * p)28005a35163SDeven Bowers static bool evaluate_property(const struct ipe_eval_ctx *const ctx,
28105a35163SDeven Bowers 			      struct ipe_prop *p)
28205a35163SDeven Bowers {
283a8a74df1SFan Wu 	switch (p->type) {
284a8a74df1SFan Wu 	case IPE_PROP_BOOT_VERIFIED_FALSE:
285a8a74df1SFan Wu 		return !evaluate_boot_verified(ctx);
286a8a74df1SFan Wu 	case IPE_PROP_BOOT_VERIFIED_TRUE:
287a8a74df1SFan Wu 		return evaluate_boot_verified(ctx);
288e155858dSDeven Bowers 	case IPE_PROP_DMV_ROOTHASH:
289e155858dSDeven Bowers 		return evaluate_dmv_roothash(ctx, p);
290e155858dSDeven Bowers 	case IPE_PROP_DMV_SIG_FALSE:
291e155858dSDeven Bowers 		return evaluate_dmv_sig_false(ctx);
292e155858dSDeven Bowers 	case IPE_PROP_DMV_SIG_TRUE:
293e155858dSDeven Bowers 		return evaluate_dmv_sig_true(ctx);
294*31f8c868SFan Wu 	case IPE_PROP_FSV_DIGEST:
295*31f8c868SFan Wu 		return evaluate_fsv_digest(ctx, p);
296*31f8c868SFan Wu 	case IPE_PROP_FSV_SIG_FALSE:
297*31f8c868SFan Wu 		return evaluate_fsv_sig_false(ctx);
298*31f8c868SFan Wu 	case IPE_PROP_FSV_SIG_TRUE:
299*31f8c868SFan Wu 		return evaluate_fsv_sig_true(ctx);
300a8a74df1SFan Wu 	default:
30105a35163SDeven Bowers 		return false;
30205a35163SDeven Bowers 	}
303a8a74df1SFan Wu }
30405a35163SDeven Bowers 
30505a35163SDeven Bowers /**
30605a35163SDeven Bowers  * ipe_evaluate_event() - Analyze @ctx against the current active policy.
30705a35163SDeven Bowers  * @ctx: Supplies a pointer to the context to be evaluated.
30805a35163SDeven Bowers  *
30905a35163SDeven Bowers  * This is the loop where all policy evaluations happen against the IPE policy.
31005a35163SDeven Bowers  *
31105a35163SDeven Bowers  * Return:
31205a35163SDeven Bowers  * * %0		- Success
31305a35163SDeven Bowers  * * %-EACCES	- @ctx did not pass evaluation
31405a35163SDeven Bowers  */
ipe_evaluate_event(const struct ipe_eval_ctx * const ctx)31505a35163SDeven Bowers int ipe_evaluate_event(const struct ipe_eval_ctx *const ctx)
31605a35163SDeven Bowers {
31705a35163SDeven Bowers 	const struct ipe_op_table *rules = NULL;
31805a35163SDeven Bowers 	const struct ipe_rule *rule = NULL;
31905a35163SDeven Bowers 	struct ipe_policy *pol = NULL;
32005a35163SDeven Bowers 	struct ipe_prop *prop = NULL;
32105a35163SDeven Bowers 	enum ipe_action_type action;
322f44554b5SDeven Bowers 	enum ipe_match match_type;
32305a35163SDeven Bowers 	bool match = false;
324a68916eaSDeven Bowers 	int rc = 0;
32505a35163SDeven Bowers 
32605a35163SDeven Bowers 	rcu_read_lock();
32705a35163SDeven Bowers 
32805a35163SDeven Bowers 	pol = rcu_dereference(ipe_active_policy);
32905a35163SDeven Bowers 	if (!pol) {
33005a35163SDeven Bowers 		rcu_read_unlock();
33105a35163SDeven Bowers 		return 0;
33205a35163SDeven Bowers 	}
33305a35163SDeven Bowers 
33405a35163SDeven Bowers 	if (ctx->op == IPE_OP_INVALID) {
335f44554b5SDeven Bowers 		if (pol->parsed->global_default_action == IPE_ACTION_INVALID) {
33605a35163SDeven Bowers 			WARN(1, "no default rule set for unknown op, ALLOW it");
337f44554b5SDeven Bowers 			action = IPE_ACTION_ALLOW;
338f44554b5SDeven Bowers 		} else {
339f44554b5SDeven Bowers 			action = pol->parsed->global_default_action;
340f44554b5SDeven Bowers 		}
341f44554b5SDeven Bowers 		match_type = IPE_MATCH_GLOBAL;
342f44554b5SDeven Bowers 		goto eval;
34305a35163SDeven Bowers 	}
34405a35163SDeven Bowers 
34505a35163SDeven Bowers 	rules = &pol->parsed->rules[ctx->op];
34605a35163SDeven Bowers 
34705a35163SDeven Bowers 	list_for_each_entry(rule, &rules->rules, next) {
34805a35163SDeven Bowers 		match = true;
34905a35163SDeven Bowers 
35005a35163SDeven Bowers 		list_for_each_entry(prop, &rule->props, next) {
35105a35163SDeven Bowers 			match = evaluate_property(ctx, prop);
35205a35163SDeven Bowers 			if (!match)
35305a35163SDeven Bowers 				break;
35405a35163SDeven Bowers 		}
35505a35163SDeven Bowers 
35605a35163SDeven Bowers 		if (match)
35705a35163SDeven Bowers 			break;
35805a35163SDeven Bowers 	}
35905a35163SDeven Bowers 
360f44554b5SDeven Bowers 	if (match) {
36105a35163SDeven Bowers 		action = rule->action;
362f44554b5SDeven Bowers 		match_type = IPE_MATCH_RULE;
363f44554b5SDeven Bowers 	} else if (rules->default_action != IPE_ACTION_INVALID) {
36405a35163SDeven Bowers 		action = rules->default_action;
365f44554b5SDeven Bowers 		match_type = IPE_MATCH_TABLE;
366f44554b5SDeven Bowers 	} else {
36705a35163SDeven Bowers 		action = pol->parsed->global_default_action;
368f44554b5SDeven Bowers 		match_type = IPE_MATCH_GLOBAL;
369f44554b5SDeven Bowers 	}
37005a35163SDeven Bowers 
371f44554b5SDeven Bowers eval:
372f44554b5SDeven Bowers 	ipe_audit_match(ctx, match_type, action, rule);
37305a35163SDeven Bowers 	rcu_read_unlock();
374f44554b5SDeven Bowers 
37505a35163SDeven Bowers 	if (action == IPE_ACTION_DENY)
376a68916eaSDeven Bowers 		rc = -EACCES;
37705a35163SDeven Bowers 
378a68916eaSDeven Bowers 	if (!READ_ONCE(enforce))
379a68916eaSDeven Bowers 		rc = 0;
380a68916eaSDeven Bowers 
381a68916eaSDeven Bowers 	return rc;
38205a35163SDeven Bowers }
383f44554b5SDeven Bowers 
384f44554b5SDeven Bowers /* Set the right module name */
385f44554b5SDeven Bowers #ifdef KBUILD_MODNAME
386f44554b5SDeven Bowers #undef KBUILD_MODNAME
387f44554b5SDeven Bowers #define KBUILD_MODNAME "ipe"
388f44554b5SDeven Bowers #endif
389f44554b5SDeven Bowers 
390f44554b5SDeven Bowers module_param(success_audit, bool, 0400);
391f44554b5SDeven Bowers MODULE_PARM_DESC(success_audit, "Start IPE with success auditing enabled");
392a68916eaSDeven Bowers module_param(enforce, bool, 0400);
393a68916eaSDeven Bowers MODULE_PARM_DESC(enforce, "Start IPE in enforce or permissive mode");
394