1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
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>
21 struct ipe_policy __rcu
*ipe_active_policy
;
24 #define INO_BLOCK_DEV(ino) ((ino)->i_sb->s_bdev)
26 #define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb)
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
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
));
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
);
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 */
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
)
77 build_ipe_inode_blob_ctx(ctx
, ino
);
80 static void build_ipe_inode_ctx(struct ipe_eval_ctx
*ctx
, const struct inode
*const ino
)
83 #endif /* CONFIG_IPE_PROP_FS_VERITY */
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
,
95 enum ipe_hook_type hook
)
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.
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.
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
,
137 return !!ctx
->ipe_bdev
&&
138 !!ctx
->ipe_bdev
->root_hash
&&
139 ipe_digest_eval(p
->value
,
140 ctx
->ipe_bdev
->root_hash
);
143 static bool evaluate_dmv_roothash(const struct ipe_eval_ctx
*const ctx
,
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.
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.
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
);
177 static bool evaluate_dmv_sig_false(const struct ipe_eval_ctx
*const ctx
)
182 static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx
*const ctx
)
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.
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
,
202 u8 digest
[FS_VERITY_MAX_DIGEST_SIZE
];
203 struct digest_info info
;
207 if (!fsverity_get_digest((struct inode
*)ctx
->ino
,
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
);
220 static bool evaluate_fsv_digest(const struct ipe_eval_ctx
*const ctx
,
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.
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
)
239 !IS_VERITY(ctx
->ino
) ||
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.
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
);
257 static bool evaluate_fsv_sig_false(const struct ipe_eval_ctx
*const ctx
)
262 static bool evaluate_fsv_sig_true(const struct ipe_eval_ctx
*const ctx
)
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.
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
,
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
);
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.
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
;
328 pol
= rcu_dereference(ipe_active_policy
);
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
;
339 action
= pol
->parsed
->global_default_action
;
341 match_type
= IPE_MATCH_GLOBAL
;
345 rules
= &pol
->parsed
->rules
[ctx
->op
];
347 list_for_each_entry(rule
, &rules
->rules
, next
) {
350 list_for_each_entry(prop
, &rule
->props
, next
) {
351 match
= evaluate_property(ctx
, prop
);
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
;
367 action
= pol
->parsed
->global_default_action
;
368 match_type
= IPE_MATCH_GLOBAL
;
372 ipe_audit_match(ctx
, match_type
, action
, rule
);
375 if (action
== IPE_ACTION_DENY
)
378 if (!READ_ONCE(enforce
))
384 /* Set the right module name */
385 #ifdef KBUILD_MODNAME
386 #undef KBUILD_MODNAME
387 #define KBUILD_MODNAME "ipe"
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");