~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/security/ipe/eval.c

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 #include <linux/moduleparam.h>
 13 #include <linux/fsverity.h>
 14 
 15 #include "ipe.h"
 16 #include "eval.h"
 17 #include "policy.h"
 18 #include "audit.h"
 19 #include "digest.h"
 20 
 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)
 25 
 26 #define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb)
 27 
 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.
 32  */
 33 static void build_ipe_sb_ctx(struct ipe_eval_ctx *ctx, const struct file *const file)
 34 {
 35         ctx->initramfs = ipe_sb(FILE_SUPERBLOCK(file))->initramfs;
 36 }
 37 
 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.
 43  */
 44 static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
 45 {
 46         if (INO_BLOCK_DEV(ino))
 47                 ctx->ipe_bdev = ipe_bdev(INO_BLOCK_DEV(ino));
 48 }
 49 #else
 50 static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
 51 {
 52 }
 53 #endif /* CONFIG_IPE_PROP_DM_VERITY */
 54 
 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)
 59 {
 60         ctx->ipe_inode = ipe_inode(ctx->ino);
 61 }
 62 #else
 63 static inline void build_ipe_inode_blob_ctx(struct ipe_eval_ctx *ctx,
 64                                             const struct inode *const ino)
 65 {
 66 }
 67 #endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
 68 
 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.
 73  */
 74 static void build_ipe_inode_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
 75 {
 76         ctx->ino = ino;
 77         build_ipe_inode_blob_ctx(ctx, ino);
 78 }
 79 #else
 80 static void build_ipe_inode_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
 81 {
 82 }
 83 #endif /* CONFIG_IPE_PROP_FS_VERITY */
 84 
 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.
 91  */
 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)
 96 {
 97         struct inode *ino;
 98 
 99         ctx->file = file;
100         ctx->op = op;
101         ctx->hook = hook;
102 
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);
108         }
109 }
110 
111 /**
112  * evaluate_boot_verified() - Evaluate @ctx for the boot verified property.
113  * @ctx: Supplies a pointer to the context being evaluated.
114  *
115  * Return:
116  * * %true      - The current @ctx match the @p
117  * * %false     - The current @ctx doesn't match the @p
118  */
119 static bool evaluate_boot_verified(const struct ipe_eval_ctx *const ctx)
120 {
121         return ctx->initramfs;
122 }
123 
124 #ifdef CONFIG_IPE_PROP_DM_VERITY
125 /**
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.
129  *
130  * Return:
131  * * %true      - The current @ctx match the @p
132  * * %false     - The current @ctx doesn't match the @p
133  */
134 static bool evaluate_dmv_roothash(const struct ipe_eval_ctx *const ctx,
135                                   struct ipe_prop *p)
136 {
137         return !!ctx->ipe_bdev &&
138                !!ctx->ipe_bdev->root_hash &&
139                ipe_digest_eval(p->value,
140                                ctx->ipe_bdev->root_hash);
141 }
142 #else
143 static bool evaluate_dmv_roothash(const struct ipe_eval_ctx *const ctx,
144                                   struct ipe_prop *p)
145 {
146         return false;
147 }
148 #endif /* CONFIG_IPE_PROP_DM_VERITY */
149 
150 #ifdef CONFIG_IPE_PROP_DM_VERITY_SIGNATURE
151 /**
152  * evaluate_dmv_sig_false() - Evaluate @ctx against a dmv sig false property.
153  * @ctx: Supplies a pointer to the context being evaluated.
154  *
155  * Return:
156  * * %true      - The current @ctx match the property
157  * * %false     - The current @ctx doesn't match the property
158  */
159 static bool evaluate_dmv_sig_false(const struct ipe_eval_ctx *const ctx)
160 {
161         return !ctx->ipe_bdev || (!ctx->ipe_bdev->dm_verity_signed);
162 }
163 
164 /**
165  * evaluate_dmv_sig_true() - Evaluate @ctx against a dmv sig true property.
166  * @ctx: Supplies a pointer to the context being evaluated.
167  *
168  * Return:
169  * * %true      - The current @ctx match the property
170  * * %false     - The current @ctx doesn't match the property
171  */
172 static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx *const ctx)
173 {
174         return !evaluate_dmv_sig_false(ctx);
175 }
176 #else
177 static bool evaluate_dmv_sig_false(const struct ipe_eval_ctx *const ctx)
178 {
179         return false;
180 }
181 
182 static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx *const ctx)
183 {
184         return false;
185 }
186 #endif /* CONFIG_IPE_PROP_DM_VERITY_SIGNATURE */
187 
188 #ifdef CONFIG_IPE_PROP_FS_VERITY
189 /**
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.
193  *
194  * Return:
195  * * %true      - The current @ctx match the @p
196  * * %false     - The current @ctx doesn't match the @p
197  */
198 static bool evaluate_fsv_digest(const struct ipe_eval_ctx *const ctx,
199                                 struct ipe_prop *p)
200 {
201         enum hash_algo alg;
202         u8 digest[FS_VERITY_MAX_DIGEST_SIZE];
203         struct digest_info info;
204 
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;
212 
213         info.alg = hash_algo_name[alg];
214         info.digest = digest;
215         info.digest_len = hash_digest_size[alg];
216 
217         return ipe_digest_eval(p->value, &info);
218 }
219 #else
220 static bool evaluate_fsv_digest(const struct ipe_eval_ctx *const ctx,
221                                 struct ipe_prop *p)
222 {
223         return false;
224 }
225 #endif /* CONFIG_IPE_PROP_FS_VERITY */
226 
227 #ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
228 /**
229  * evaluate_fsv_sig_false() - Evaluate @ctx against a fsv sig false property.
230  * @ctx: Supplies a pointer to the context being evaluated.
231  *
232  * Return:
233  * * %true      - The current @ctx match the property
234  * * %false     - The current @ctx doesn't match the property
235  */
236 static bool evaluate_fsv_sig_false(const struct ipe_eval_ctx *const ctx)
237 {
238         return !ctx->ino ||
239                !IS_VERITY(ctx->ino) ||
240                !ctx->ipe_inode ||
241                !ctx->ipe_inode->fs_verity_signed;
242 }
243 
244 /**
245  * evaluate_fsv_sig_true() - Evaluate @ctx against a fsv sig true property.
246  * @ctx: Supplies a pointer to the context being evaluated.
247  *
248  * Return:
249  * * %true - The current @ctx match the property
250  * * %false - The current @ctx doesn't match the property
251  */
252 static bool evaluate_fsv_sig_true(const struct ipe_eval_ctx *const ctx)
253 {
254         return !evaluate_fsv_sig_false(ctx);
255 }
256 #else
257 static bool evaluate_fsv_sig_false(const struct ipe_eval_ctx *const ctx)
258 {
259         return false;
260 }
261 
262 static bool evaluate_fsv_sig_true(const struct ipe_eval_ctx *const ctx)
263 {
264         return false;
265 }
266 #endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
267 
268 /**
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.
272  *
273  * This function Determines whether the specified @ctx
274  * matches the conditions defined by a rule property @p.
275  *
276  * Return:
277  * * %true      - The current @ctx match the @p
278  * * %false     - The current @ctx doesn't match the @p
279  */
280 static bool evaluate_property(const struct ipe_eval_ctx *const ctx,
281                               struct ipe_prop *p)
282 {
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;
302         }
303 }
304 
305 /**
306  * ipe_evaluate_event() - Analyze @ctx against the current active policy.
307  * @ctx: Supplies a pointer to the context to be evaluated.
308  *
309  * This is the loop where all policy evaluations happen against the IPE policy.
310  *
311  * Return:
312  * * %0         - Success
313  * * %-EACCES   - @ctx did not pass evaluation
314  */
315 int ipe_evaluate_event(const struct ipe_eval_ctx *const ctx)
316 {
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;
325 
326         rcu_read_lock();
327 
328         pol = rcu_dereference(ipe_active_policy);
329         if (!pol) {
330                 rcu_read_unlock();
331                 return 0;
332         }
333 
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;
340                 }
341                 match_type = IPE_MATCH_GLOBAL;
342                 goto eval;
343         }
344 
345         rules = &pol->parsed->rules[ctx->op];
346 
347         list_for_each_entry(rule, &rules->rules, next) {
348                 match = true;
349 
350                 list_for_each_entry(prop, &rule->props, next) {
351                         match = evaluate_property(ctx, prop);
352                         if (!match)
353                                 break;
354                 }
355 
356                 if (match)
357                         break;
358         }
359 
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;
369         }
370 
371 eval:
372         ipe_audit_match(ctx, match_type, action, rule);
373         rcu_read_unlock();
374 
375         if (action == IPE_ACTION_DENY)
376                 rc = -EACCES;
377 
378         if (!READ_ONCE(enforce))
379                 rc = 0;
380 
381         return rc;
382 }
383 
384 /* Set the right module name */
385 #ifdef KBUILD_MODNAME
386 #undef KBUILD_MODNAME
387 #define KBUILD_MODNAME "ipe"
388 #endif
389 
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");
394 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php