drm/rockchip: dw_hdmi_qp: Add basic RK3576 HDMI output support
[drm/drm-misc.git] / security / ipe / eval.c
blob21439c5be33648d6ce5f14b8f5f000b3dab17220
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
4 */
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 #include <linux/moduleparam.h>
13 #include <linux/fsverity.h>
15 #include "ipe.h"
16 #include "eval.h"
17 #include "policy.h"
18 #include "audit.h"
19 #include "digest.h"
21 struct ipe_policy __rcu *ipe_active_policy;
22 bool success_audit;
23 bool enforce = true;
24 #define INO_BLOCK_DEV(ino) ((ino)->i_sb->s_bdev)
26 #define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb)
28 /**
29 * build_ipe_sb_ctx() - Build initramfs field of an ipe evaluation context.
30 * @ctx: Supplies a pointer to the context to be populated.
31 * @file: Supplies the file struct of the file triggered IPE event.
33 static void build_ipe_sb_ctx(struct ipe_eval_ctx *ctx, const struct file *const file)
35 ctx->initramfs = ipe_sb(FILE_SUPERBLOCK(file))->initramfs;
38 #ifdef CONFIG_IPE_PROP_DM_VERITY
39 /**
40 * build_ipe_bdev_ctx() - Build ipe_bdev field of an evaluation context.
41 * @ctx: Supplies a pointer to the context to be populated.
42 * @ino: Supplies the inode struct of the file triggered IPE event.
44 static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
46 if (INO_BLOCK_DEV(ino))
47 ctx->ipe_bdev = ipe_bdev(INO_BLOCK_DEV(ino));
49 #else
50 static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
53 #endif /* CONFIG_IPE_PROP_DM_VERITY */
55 #ifdef CONFIG_IPE_PROP_FS_VERITY
56 #ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
57 static void build_ipe_inode_blob_ctx(struct ipe_eval_ctx *ctx,
58 const struct inode *const ino)
60 ctx->ipe_inode = ipe_inode(ctx->ino);
62 #else
63 static inline void build_ipe_inode_blob_ctx(struct ipe_eval_ctx *ctx,
64 const struct inode *const ino)
67 #endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
69 /**
70 * build_ipe_inode_ctx() - Build inode fields of an evaluation context.
71 * @ctx: Supplies a pointer to the context to be populated.
72 * @ino: Supplies the inode struct of the file triggered IPE event.
74 static void build_ipe_inode_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
76 ctx->ino = ino;
77 build_ipe_inode_blob_ctx(ctx, ino);
79 #else
80 static void build_ipe_inode_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
83 #endif /* CONFIG_IPE_PROP_FS_VERITY */
85 /**
86 * ipe_build_eval_ctx() - Build an ipe evaluation context.
87 * @ctx: Supplies a pointer to the context to be populated.
88 * @file: Supplies a pointer to the file to associated with the evaluation.
89 * @op: Supplies the IPE policy operation associated with the evaluation.
90 * @hook: Supplies the LSM hook associated with the evaluation.
92 void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx,
93 const struct file *file,
94 enum ipe_op_type op,
95 enum ipe_hook_type hook)
97 struct inode *ino;
99 ctx->file = file;
100 ctx->op = op;
101 ctx->hook = hook;
103 if (file) {
104 build_ipe_sb_ctx(ctx, file);
105 ino = d_real_inode(file->f_path.dentry);
106 build_ipe_bdev_ctx(ctx, ino);
107 build_ipe_inode_ctx(ctx, ino);
112 * evaluate_boot_verified() - Evaluate @ctx for the boot verified property.
113 * @ctx: Supplies a pointer to the context being evaluated.
115 * Return:
116 * * %true - The current @ctx match the @p
117 * * %false - The current @ctx doesn't match the @p
119 static bool evaluate_boot_verified(const struct ipe_eval_ctx *const ctx)
121 return ctx->initramfs;
124 #ifdef CONFIG_IPE_PROP_DM_VERITY
126 * evaluate_dmv_roothash() - Evaluate @ctx against a dmv roothash property.
127 * @ctx: Supplies a pointer to the context being evaluated.
128 * @p: Supplies a pointer to the property being evaluated.
130 * Return:
131 * * %true - The current @ctx match the @p
132 * * %false - The current @ctx doesn't match the @p
134 static bool evaluate_dmv_roothash(const struct ipe_eval_ctx *const ctx,
135 struct ipe_prop *p)
137 return !!ctx->ipe_bdev &&
138 !!ctx->ipe_bdev->root_hash &&
139 ipe_digest_eval(p->value,
140 ctx->ipe_bdev->root_hash);
142 #else
143 static bool evaluate_dmv_roothash(const struct ipe_eval_ctx *const ctx,
144 struct ipe_prop *p)
146 return false;
148 #endif /* CONFIG_IPE_PROP_DM_VERITY */
150 #ifdef CONFIG_IPE_PROP_DM_VERITY_SIGNATURE
152 * evaluate_dmv_sig_false() - Evaluate @ctx against a dmv sig false property.
153 * @ctx: Supplies a pointer to the context being evaluated.
155 * Return:
156 * * %true - The current @ctx match the property
157 * * %false - The current @ctx doesn't match the property
159 static bool evaluate_dmv_sig_false(const struct ipe_eval_ctx *const ctx)
161 return !ctx->ipe_bdev || (!ctx->ipe_bdev->dm_verity_signed);
165 * evaluate_dmv_sig_true() - Evaluate @ctx against a dmv sig true property.
166 * @ctx: Supplies a pointer to the context being evaluated.
168 * Return:
169 * * %true - The current @ctx match the property
170 * * %false - The current @ctx doesn't match the property
172 static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx *const ctx)
174 return !evaluate_dmv_sig_false(ctx);
176 #else
177 static bool evaluate_dmv_sig_false(const struct ipe_eval_ctx *const ctx)
179 return false;
182 static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx *const ctx)
184 return false;
186 #endif /* CONFIG_IPE_PROP_DM_VERITY_SIGNATURE */
188 #ifdef CONFIG_IPE_PROP_FS_VERITY
190 * evaluate_fsv_digest() - Evaluate @ctx against a fsv digest property.
191 * @ctx: Supplies a pointer to the context being evaluated.
192 * @p: Supplies a pointer to the property being evaluated.
194 * Return:
195 * * %true - The current @ctx match the @p
196 * * %false - The current @ctx doesn't match the @p
198 static bool evaluate_fsv_digest(const struct ipe_eval_ctx *const ctx,
199 struct ipe_prop *p)
201 enum hash_algo alg;
202 u8 digest[FS_VERITY_MAX_DIGEST_SIZE];
203 struct digest_info info;
205 if (!ctx->ino)
206 return false;
207 if (!fsverity_get_digest((struct inode *)ctx->ino,
208 digest,
209 NULL,
210 &alg))
211 return false;
213 info.alg = hash_algo_name[alg];
214 info.digest = digest;
215 info.digest_len = hash_digest_size[alg];
217 return ipe_digest_eval(p->value, &info);
219 #else
220 static bool evaluate_fsv_digest(const struct ipe_eval_ctx *const ctx,
221 struct ipe_prop *p)
223 return false;
225 #endif /* CONFIG_IPE_PROP_FS_VERITY */
227 #ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
229 * evaluate_fsv_sig_false() - Evaluate @ctx against a fsv sig false property.
230 * @ctx: Supplies a pointer to the context being evaluated.
232 * Return:
233 * * %true - The current @ctx match the property
234 * * %false - The current @ctx doesn't match the property
236 static bool evaluate_fsv_sig_false(const struct ipe_eval_ctx *const ctx)
238 return !ctx->ino ||
239 !IS_VERITY(ctx->ino) ||
240 !ctx->ipe_inode ||
241 !ctx->ipe_inode->fs_verity_signed;
245 * evaluate_fsv_sig_true() - Evaluate @ctx against a fsv sig true property.
246 * @ctx: Supplies a pointer to the context being evaluated.
248 * Return:
249 * * %true - The current @ctx match the property
250 * * %false - The current @ctx doesn't match the property
252 static bool evaluate_fsv_sig_true(const struct ipe_eval_ctx *const ctx)
254 return !evaluate_fsv_sig_false(ctx);
256 #else
257 static bool evaluate_fsv_sig_false(const struct ipe_eval_ctx *const ctx)
259 return false;
262 static bool evaluate_fsv_sig_true(const struct ipe_eval_ctx *const ctx)
264 return false;
266 #endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
269 * evaluate_property() - Analyze @ctx against a rule property.
270 * @ctx: Supplies a pointer to the context to be evaluated.
271 * @p: Supplies a pointer to the property to be evaluated.
273 * This function Determines whether the specified @ctx
274 * matches the conditions defined by a rule property @p.
276 * Return:
277 * * %true - The current @ctx match the @p
278 * * %false - The current @ctx doesn't match the @p
280 static bool evaluate_property(const struct ipe_eval_ctx *const ctx,
281 struct ipe_prop *p)
283 switch (p->type) {
284 case IPE_PROP_BOOT_VERIFIED_FALSE:
285 return !evaluate_boot_verified(ctx);
286 case IPE_PROP_BOOT_VERIFIED_TRUE:
287 return evaluate_boot_verified(ctx);
288 case IPE_PROP_DMV_ROOTHASH:
289 return evaluate_dmv_roothash(ctx, p);
290 case IPE_PROP_DMV_SIG_FALSE:
291 return evaluate_dmv_sig_false(ctx);
292 case IPE_PROP_DMV_SIG_TRUE:
293 return evaluate_dmv_sig_true(ctx);
294 case IPE_PROP_FSV_DIGEST:
295 return evaluate_fsv_digest(ctx, p);
296 case IPE_PROP_FSV_SIG_FALSE:
297 return evaluate_fsv_sig_false(ctx);
298 case IPE_PROP_FSV_SIG_TRUE:
299 return evaluate_fsv_sig_true(ctx);
300 default:
301 return false;
306 * ipe_evaluate_event() - Analyze @ctx against the current active policy.
307 * @ctx: Supplies a pointer to the context to be evaluated.
309 * This is the loop where all policy evaluations happen against the IPE policy.
311 * Return:
312 * * %0 - Success
313 * * %-EACCES - @ctx did not pass evaluation
315 int ipe_evaluate_event(const struct ipe_eval_ctx *const ctx)
317 const struct ipe_op_table *rules = NULL;
318 const struct ipe_rule *rule = NULL;
319 struct ipe_policy *pol = NULL;
320 struct ipe_prop *prop = NULL;
321 enum ipe_action_type action;
322 enum ipe_match match_type;
323 bool match = false;
324 int rc = 0;
326 rcu_read_lock();
328 pol = rcu_dereference(ipe_active_policy);
329 if (!pol) {
330 rcu_read_unlock();
331 return 0;
334 if (ctx->op == IPE_OP_INVALID) {
335 if (pol->parsed->global_default_action == IPE_ACTION_INVALID) {
336 WARN(1, "no default rule set for unknown op, ALLOW it");
337 action = IPE_ACTION_ALLOW;
338 } else {
339 action = pol->parsed->global_default_action;
341 match_type = IPE_MATCH_GLOBAL;
342 goto eval;
345 rules = &pol->parsed->rules[ctx->op];
347 list_for_each_entry(rule, &rules->rules, next) {
348 match = true;
350 list_for_each_entry(prop, &rule->props, next) {
351 match = evaluate_property(ctx, prop);
352 if (!match)
353 break;
356 if (match)
357 break;
360 if (match) {
361 action = rule->action;
362 match_type = IPE_MATCH_RULE;
363 } else if (rules->default_action != IPE_ACTION_INVALID) {
364 action = rules->default_action;
365 match_type = IPE_MATCH_TABLE;
366 } else {
367 action = pol->parsed->global_default_action;
368 match_type = IPE_MATCH_GLOBAL;
371 eval:
372 ipe_audit_match(ctx, match_type, action, rule);
373 rcu_read_unlock();
375 if (action == IPE_ACTION_DENY)
376 rc = -EACCES;
378 if (!READ_ONCE(enforce))
379 rc = 0;
381 return rc;
384 /* Set the right module name */
385 #ifdef KBUILD_MODNAME
386 #undef KBUILD_MODNAME
387 #define KBUILD_MODNAME "ipe"
388 #endif
390 module_param(success_audit, bool, 0400);
391 MODULE_PARM_DESC(success_audit, "Start IPE with success auditing enabled");
392 module_param(enforce, bool, 0400);
393 MODULE_PARM_DESC(enforce, "Start IPE in enforce or permissive mode");