eval.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
  4. */
  5. #include <linux/fs.h>
  6. #include <linux/types.h>
  7. #include <linux/slab.h>
  8. #include <linux/file.h>
  9. #include <linux/sched.h>
  10. #include <linux/rcupdate.h>
  11. #include <linux/moduleparam.h>
  12. #include <linux/fsverity.h>
  13. #include "ipe.h"
  14. #include "eval.h"
  15. #include "policy.h"
  16. #include "audit.h"
  17. #include "digest.h"
  18. struct ipe_policy __rcu *ipe_active_policy;
  19. bool success_audit;
  20. bool enforce = true;
  21. #define INO_BLOCK_DEV(ino) ((ino)->i_sb->s_bdev)
  22. #define FILE_SUPERBLOCK(f) ((f)->f_path.mnt->mnt_sb)
  23. /**
  24. * build_ipe_sb_ctx() - Build initramfs field of an ipe evaluation context.
  25. * @ctx: Supplies a pointer to the context to be populated.
  26. * @file: Supplies the file struct of the file triggered IPE event.
  27. */
  28. static void build_ipe_sb_ctx(struct ipe_eval_ctx *ctx, const struct file *const file)
  29. {
  30. ctx->initramfs = ipe_sb(FILE_SUPERBLOCK(file))->initramfs;
  31. }
  32. #ifdef CONFIG_IPE_PROP_DM_VERITY
  33. /**
  34. * build_ipe_bdev_ctx() - Build ipe_bdev field of an evaluation context.
  35. * @ctx: Supplies a pointer to the context to be populated.
  36. * @ino: Supplies the inode struct of the file triggered IPE event.
  37. */
  38. static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
  39. {
  40. if (INO_BLOCK_DEV(ino))
  41. ctx->ipe_bdev = ipe_bdev(INO_BLOCK_DEV(ino));
  42. }
  43. #else
  44. static void build_ipe_bdev_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
  45. {
  46. }
  47. #endif /* CONFIG_IPE_PROP_DM_VERITY */
  48. #ifdef CONFIG_IPE_PROP_FS_VERITY
  49. #ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
  50. static void build_ipe_inode_blob_ctx(struct ipe_eval_ctx *ctx,
  51. const struct inode *const ino)
  52. {
  53. ctx->ipe_inode = ipe_inode(ctx->ino);
  54. }
  55. #else
  56. static inline void build_ipe_inode_blob_ctx(struct ipe_eval_ctx *ctx,
  57. const struct inode *const ino)
  58. {
  59. }
  60. #endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
  61. /**
  62. * build_ipe_inode_ctx() - Build inode fields of an evaluation context.
  63. * @ctx: Supplies a pointer to the context to be populated.
  64. * @ino: Supplies the inode struct of the file triggered IPE event.
  65. */
  66. static void build_ipe_inode_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
  67. {
  68. ctx->ino = ino;
  69. build_ipe_inode_blob_ctx(ctx, ino);
  70. }
  71. #else
  72. static void build_ipe_inode_ctx(struct ipe_eval_ctx *ctx, const struct inode *const ino)
  73. {
  74. }
  75. #endif /* CONFIG_IPE_PROP_FS_VERITY */
  76. /**
  77. * ipe_build_eval_ctx() - Build an ipe evaluation context.
  78. * @ctx: Supplies a pointer to the context to be populated.
  79. * @file: Supplies a pointer to the file to associated with the evaluation.
  80. * @op: Supplies the IPE policy operation associated with the evaluation.
  81. * @hook: Supplies the LSM hook associated with the evaluation.
  82. */
  83. void ipe_build_eval_ctx(struct ipe_eval_ctx *ctx,
  84. const struct file *file,
  85. enum ipe_op_type op,
  86. enum ipe_hook_type hook)
  87. {
  88. struct inode *ino;
  89. ctx->file = file;
  90. ctx->op = op;
  91. ctx->hook = hook;
  92. if (file) {
  93. build_ipe_sb_ctx(ctx, file);
  94. ino = d_real_inode(file->f_path.dentry);
  95. build_ipe_bdev_ctx(ctx, ino);
  96. build_ipe_inode_ctx(ctx, ino);
  97. }
  98. }
  99. /**
  100. * evaluate_boot_verified() - Evaluate @ctx for the boot verified property.
  101. * @ctx: Supplies a pointer to the context being evaluated.
  102. *
  103. * Return:
  104. * * %true - The current @ctx match the @p
  105. * * %false - The current @ctx doesn't match the @p
  106. */
  107. static bool evaluate_boot_verified(const struct ipe_eval_ctx *const ctx)
  108. {
  109. return ctx->initramfs;
  110. }
  111. #ifdef CONFIG_IPE_PROP_DM_VERITY
  112. /**
  113. * evaluate_dmv_roothash() - Evaluate @ctx against a dmv roothash property.
  114. * @ctx: Supplies a pointer to the context being evaluated.
  115. * @p: Supplies a pointer to the property being evaluated.
  116. *
  117. * Return:
  118. * * %true - The current @ctx match the @p
  119. * * %false - The current @ctx doesn't match the @p
  120. */
  121. static bool evaluate_dmv_roothash(const struct ipe_eval_ctx *const ctx,
  122. struct ipe_prop *p)
  123. {
  124. return !!ctx->ipe_bdev &&
  125. !!ctx->ipe_bdev->root_hash &&
  126. ipe_digest_eval(p->value,
  127. ctx->ipe_bdev->root_hash);
  128. }
  129. #else
  130. static bool evaluate_dmv_roothash(const struct ipe_eval_ctx *const ctx,
  131. struct ipe_prop *p)
  132. {
  133. return false;
  134. }
  135. #endif /* CONFIG_IPE_PROP_DM_VERITY */
  136. #ifdef CONFIG_IPE_PROP_DM_VERITY_SIGNATURE
  137. /**
  138. * evaluate_dmv_sig_false() - Evaluate @ctx against a dmv sig false property.
  139. * @ctx: Supplies a pointer to the context being evaluated.
  140. *
  141. * Return:
  142. * * %true - The current @ctx match the property
  143. * * %false - The current @ctx doesn't match the property
  144. */
  145. static bool evaluate_dmv_sig_false(const struct ipe_eval_ctx *const ctx)
  146. {
  147. return !ctx->ipe_bdev || (!ctx->ipe_bdev->dm_verity_signed);
  148. }
  149. /**
  150. * evaluate_dmv_sig_true() - Evaluate @ctx against a dmv sig true property.
  151. * @ctx: Supplies a pointer to the context being evaluated.
  152. *
  153. * Return:
  154. * * %true - The current @ctx match the property
  155. * * %false - The current @ctx doesn't match the property
  156. */
  157. static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx *const ctx)
  158. {
  159. return !evaluate_dmv_sig_false(ctx);
  160. }
  161. #else
  162. static bool evaluate_dmv_sig_false(const struct ipe_eval_ctx *const ctx)
  163. {
  164. return false;
  165. }
  166. static bool evaluate_dmv_sig_true(const struct ipe_eval_ctx *const ctx)
  167. {
  168. return false;
  169. }
  170. #endif /* CONFIG_IPE_PROP_DM_VERITY_SIGNATURE */
  171. #ifdef CONFIG_IPE_PROP_FS_VERITY
  172. /**
  173. * evaluate_fsv_digest() - Evaluate @ctx against a fsv digest property.
  174. * @ctx: Supplies a pointer to the context being evaluated.
  175. * @p: Supplies a pointer to the property being evaluated.
  176. *
  177. * Return:
  178. * * %true - The current @ctx match the @p
  179. * * %false - The current @ctx doesn't match the @p
  180. */
  181. static bool evaluate_fsv_digest(const struct ipe_eval_ctx *const ctx,
  182. struct ipe_prop *p)
  183. {
  184. enum hash_algo alg;
  185. u8 digest[FS_VERITY_MAX_DIGEST_SIZE];
  186. struct digest_info info;
  187. if (!ctx->ino)
  188. return false;
  189. if (!fsverity_get_digest((struct inode *)ctx->ino,
  190. digest,
  191. NULL,
  192. &alg))
  193. return false;
  194. info.alg = hash_algo_name[alg];
  195. info.digest = digest;
  196. info.digest_len = hash_digest_size[alg];
  197. return ipe_digest_eval(p->value, &info);
  198. }
  199. #else
  200. static bool evaluate_fsv_digest(const struct ipe_eval_ctx *const ctx,
  201. struct ipe_prop *p)
  202. {
  203. return false;
  204. }
  205. #endif /* CONFIG_IPE_PROP_FS_VERITY */
  206. #ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
  207. /**
  208. * evaluate_fsv_sig_false() - Evaluate @ctx against a fsv sig false property.
  209. * @ctx: Supplies a pointer to the context being evaluated.
  210. *
  211. * Return:
  212. * * %true - The current @ctx match the property
  213. * * %false - The current @ctx doesn't match the property
  214. */
  215. static bool evaluate_fsv_sig_false(const struct ipe_eval_ctx *const ctx)
  216. {
  217. return !ctx->ino ||
  218. !IS_VERITY(ctx->ino) ||
  219. !ctx->ipe_inode ||
  220. !ctx->ipe_inode->fs_verity_signed;
  221. }
  222. /**
  223. * evaluate_fsv_sig_true() - Evaluate @ctx against a fsv sig true property.
  224. * @ctx: Supplies a pointer to the context being evaluated.
  225. *
  226. * Return:
  227. * * %true - The current @ctx match the property
  228. * * %false - The current @ctx doesn't match the property
  229. */
  230. static bool evaluate_fsv_sig_true(const struct ipe_eval_ctx *const ctx)
  231. {
  232. return !evaluate_fsv_sig_false(ctx);
  233. }
  234. #else
  235. static bool evaluate_fsv_sig_false(const struct ipe_eval_ctx *const ctx)
  236. {
  237. return false;
  238. }
  239. static bool evaluate_fsv_sig_true(const struct ipe_eval_ctx *const ctx)
  240. {
  241. return false;
  242. }
  243. #endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */
  244. /**
  245. * evaluate_property() - Analyze @ctx against a rule property.
  246. * @ctx: Supplies a pointer to the context to be evaluated.
  247. * @p: Supplies a pointer to the property to be evaluated.
  248. *
  249. * This function Determines whether the specified @ctx
  250. * matches the conditions defined by a rule property @p.
  251. *
  252. * Return:
  253. * * %true - The current @ctx match the @p
  254. * * %false - The current @ctx doesn't match the @p
  255. */
  256. static bool evaluate_property(const struct ipe_eval_ctx *const ctx,
  257. struct ipe_prop *p)
  258. {
  259. switch (p->type) {
  260. case IPE_PROP_BOOT_VERIFIED_FALSE:
  261. return !evaluate_boot_verified(ctx);
  262. case IPE_PROP_BOOT_VERIFIED_TRUE:
  263. return evaluate_boot_verified(ctx);
  264. case IPE_PROP_DMV_ROOTHASH:
  265. return evaluate_dmv_roothash(ctx, p);
  266. case IPE_PROP_DMV_SIG_FALSE:
  267. return evaluate_dmv_sig_false(ctx);
  268. case IPE_PROP_DMV_SIG_TRUE:
  269. return evaluate_dmv_sig_true(ctx);
  270. case IPE_PROP_FSV_DIGEST:
  271. return evaluate_fsv_digest(ctx, p);
  272. case IPE_PROP_FSV_SIG_FALSE:
  273. return evaluate_fsv_sig_false(ctx);
  274. case IPE_PROP_FSV_SIG_TRUE:
  275. return evaluate_fsv_sig_true(ctx);
  276. default:
  277. return false;
  278. }
  279. }
  280. /**
  281. * ipe_evaluate_event() - Analyze @ctx against the current active policy.
  282. * @ctx: Supplies a pointer to the context to be evaluated.
  283. *
  284. * This is the loop where all policy evaluations happen against the IPE policy.
  285. *
  286. * Return:
  287. * * %0 - Success
  288. * * %-EACCES - @ctx did not pass evaluation
  289. */
  290. int ipe_evaluate_event(const struct ipe_eval_ctx *const ctx)
  291. {
  292. const struct ipe_op_table *rules = NULL;
  293. const struct ipe_rule *rule = NULL;
  294. struct ipe_policy *pol = NULL;
  295. struct ipe_prop *prop = NULL;
  296. enum ipe_action_type action;
  297. enum ipe_match match_type;
  298. bool match = false;
  299. int rc = 0;
  300. rcu_read_lock();
  301. pol = rcu_dereference(ipe_active_policy);
  302. if (!pol) {
  303. rcu_read_unlock();
  304. return 0;
  305. }
  306. if (ctx->op == IPE_OP_INVALID) {
  307. if (pol->parsed->global_default_action == IPE_ACTION_INVALID) {
  308. WARN(1, "no default rule set for unknown op, ALLOW it");
  309. action = IPE_ACTION_ALLOW;
  310. } else {
  311. action = pol->parsed->global_default_action;
  312. }
  313. match_type = IPE_MATCH_GLOBAL;
  314. goto eval;
  315. }
  316. rules = &pol->parsed->rules[ctx->op];
  317. list_for_each_entry(rule, &rules->rules, next) {
  318. match = true;
  319. list_for_each_entry(prop, &rule->props, next) {
  320. match = evaluate_property(ctx, prop);
  321. if (!match)
  322. break;
  323. }
  324. if (match)
  325. break;
  326. }
  327. if (match) {
  328. action = rule->action;
  329. match_type = IPE_MATCH_RULE;
  330. } else if (rules->default_action != IPE_ACTION_INVALID) {
  331. action = rules->default_action;
  332. match_type = IPE_MATCH_TABLE;
  333. } else {
  334. action = pol->parsed->global_default_action;
  335. match_type = IPE_MATCH_GLOBAL;
  336. }
  337. eval:
  338. ipe_audit_match(ctx, match_type, action, rule);
  339. rcu_read_unlock();
  340. if (action == IPE_ACTION_DENY)
  341. rc = -EACCES;
  342. if (!READ_ONCE(enforce))
  343. rc = 0;
  344. return rc;
  345. }
  346. /* Set the right module name */
  347. #ifdef KBUILD_MODNAME
  348. #undef KBUILD_MODNAME
  349. #define KBUILD_MODNAME "ipe"
  350. #endif
  351. module_param(success_audit, bool, 0400);
  352. MODULE_PARM_DESC(success_audit, "Start IPE with success auditing enabled");
  353. module_param(enforce, bool, 0400);
  354. MODULE_PARM_DESC(enforce, "Start IPE in enforce or permissive mode");