hooks.c 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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/fs_struct.h>
  7. #include <linux/types.h>
  8. #include <linux/binfmts.h>
  9. #include <linux/mman.h>
  10. #include <linux/blk_types.h>
  11. #include "ipe.h"
  12. #include "hooks.h"
  13. #include "eval.h"
  14. #include "digest.h"
  15. /**
  16. * ipe_bprm_check_security() - ipe security hook function for bprm check.
  17. * @bprm: Supplies a pointer to a linux_binprm structure to source the file
  18. * being evaluated.
  19. *
  20. * This LSM hook is called when a binary is loaded through the exec
  21. * family of system calls.
  22. *
  23. * Return:
  24. * * %0 - Success
  25. * * %-EACCES - Did not pass IPE policy
  26. */
  27. int ipe_bprm_check_security(struct linux_binprm *bprm)
  28. {
  29. struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;
  30. ipe_build_eval_ctx(&ctx, bprm->file, IPE_OP_EXEC, IPE_HOOK_BPRM_CHECK);
  31. return ipe_evaluate_event(&ctx);
  32. }
  33. /**
  34. * ipe_bprm_creds_for_exec() - ipe security hook function for bprm creds check.
  35. * @bprm: Supplies a pointer to a linux_binprm structure to source the file
  36. * being evaluated.
  37. *
  38. * This LSM hook is called when userspace signals the kernel to check a file
  39. * for execution through the execveat syscall with the AT_EXECVE_CHECK flag.
  40. * The hook triggers IPE policy evaluation on the script file and returns
  41. * the policy decision to userspace. The userspace program receives the
  42. * return code and can decide whether to proceed with script execution.
  43. *
  44. * Return:
  45. * * %0 - Success
  46. * * %-EACCES - Did not pass IPE policy
  47. */
  48. int ipe_bprm_creds_for_exec(struct linux_binprm *bprm)
  49. {
  50. struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;
  51. if (!bprm->is_check)
  52. return 0;
  53. ipe_build_eval_ctx(&ctx, bprm->file, IPE_OP_EXEC,
  54. IPE_HOOK_BPRM_CREDS_FOR_EXEC);
  55. return ipe_evaluate_event(&ctx);
  56. }
  57. /**
  58. * ipe_mmap_file() - ipe security hook function for mmap check.
  59. * @f: File being mmap'd. Can be NULL in the case of anonymous memory.
  60. * @reqprot: The requested protection on the mmap, passed from usermode.
  61. * @prot: The effective protection on the mmap, resolved from reqprot and
  62. * system configuration.
  63. * @flags: Unused.
  64. *
  65. * This hook is called when a file is loaded through the mmap
  66. * family of system calls.
  67. *
  68. * Return:
  69. * * %0 - Success
  70. * * %-EACCES - Did not pass IPE policy
  71. */
  72. int ipe_mmap_file(struct file *f, unsigned long reqprot __always_unused,
  73. unsigned long prot, unsigned long flags)
  74. {
  75. struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;
  76. if (prot & PROT_EXEC) {
  77. ipe_build_eval_ctx(&ctx, f, IPE_OP_EXEC, IPE_HOOK_MMAP);
  78. return ipe_evaluate_event(&ctx);
  79. }
  80. return 0;
  81. }
  82. /**
  83. * ipe_file_mprotect() - ipe security hook function for mprotect check.
  84. * @vma: Existing virtual memory area created by mmap or similar.
  85. * @reqprot: The requested protection on the mmap, passed from usermode.
  86. * @prot: The effective protection on the mmap, resolved from reqprot and
  87. * system configuration.
  88. *
  89. * This LSM hook is called when a mmap'd region of memory is changing
  90. * its protections via mprotect.
  91. *
  92. * Return:
  93. * * %0 - Success
  94. * * %-EACCES - Did not pass IPE policy
  95. */
  96. int ipe_file_mprotect(struct vm_area_struct *vma,
  97. unsigned long reqprot __always_unused,
  98. unsigned long prot)
  99. {
  100. struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;
  101. /* Already Executable */
  102. if (vma->vm_flags & VM_EXEC)
  103. return 0;
  104. if (prot & PROT_EXEC) {
  105. ipe_build_eval_ctx(&ctx, vma->vm_file, IPE_OP_EXEC, IPE_HOOK_MPROTECT);
  106. return ipe_evaluate_event(&ctx);
  107. }
  108. return 0;
  109. }
  110. /**
  111. * ipe_kernel_read_file() - ipe security hook function for kernel read.
  112. * @file: Supplies a pointer to the file structure being read in from disk.
  113. * @id: Supplies the enumeration identifying the purpose of the read.
  114. * @contents: Unused.
  115. *
  116. * This LSM hook is called when a file is read from disk in the kernel.
  117. *
  118. * Return:
  119. * * %0 - Success
  120. * * %-EACCES - Did not pass IPE policy
  121. */
  122. int ipe_kernel_read_file(struct file *file, enum kernel_read_file_id id,
  123. bool contents)
  124. {
  125. struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;
  126. enum ipe_op_type op;
  127. switch (id) {
  128. case READING_FIRMWARE:
  129. op = IPE_OP_FIRMWARE;
  130. break;
  131. case READING_MODULE:
  132. case READING_MODULE_COMPRESSED:
  133. op = IPE_OP_KERNEL_MODULE;
  134. break;
  135. case READING_KEXEC_INITRAMFS:
  136. op = IPE_OP_KEXEC_INITRAMFS;
  137. break;
  138. case READING_KEXEC_IMAGE:
  139. op = IPE_OP_KEXEC_IMAGE;
  140. break;
  141. case READING_POLICY:
  142. op = IPE_OP_POLICY;
  143. break;
  144. case READING_X509_CERTIFICATE:
  145. op = IPE_OP_X509;
  146. break;
  147. default:
  148. op = IPE_OP_INVALID;
  149. WARN(1, "no rule setup for kernel_read_file enum %d", id);
  150. }
  151. ipe_build_eval_ctx(&ctx, file, op, IPE_HOOK_KERNEL_READ);
  152. return ipe_evaluate_event(&ctx);
  153. }
  154. /**
  155. * ipe_kernel_load_data() - ipe security hook function for kernel load data.
  156. * @id: Supplies the enumeration identifying the purpose of the load.
  157. * @contents: Unused.
  158. *
  159. * This LSM hook is called when a data buffer provided by userspace is loading
  160. * into the kernel.
  161. *
  162. * Return:
  163. * * %0 - Success
  164. * * %-EACCES - Did not pass IPE policy
  165. */
  166. int ipe_kernel_load_data(enum kernel_load_data_id id, bool contents)
  167. {
  168. struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;
  169. enum ipe_op_type op;
  170. switch (id) {
  171. case LOADING_FIRMWARE:
  172. op = IPE_OP_FIRMWARE;
  173. break;
  174. case LOADING_MODULE:
  175. op = IPE_OP_KERNEL_MODULE;
  176. break;
  177. case LOADING_KEXEC_INITRAMFS:
  178. op = IPE_OP_KEXEC_INITRAMFS;
  179. break;
  180. case LOADING_KEXEC_IMAGE:
  181. op = IPE_OP_KEXEC_IMAGE;
  182. break;
  183. case LOADING_POLICY:
  184. op = IPE_OP_POLICY;
  185. break;
  186. case LOADING_X509_CERTIFICATE:
  187. op = IPE_OP_X509;
  188. break;
  189. default:
  190. op = IPE_OP_INVALID;
  191. WARN(1, "no rule setup for kernel_load_data enum %d", id);
  192. }
  193. ipe_build_eval_ctx(&ctx, NULL, op, IPE_HOOK_KERNEL_LOAD);
  194. return ipe_evaluate_event(&ctx);
  195. }
  196. /**
  197. * ipe_unpack_initramfs() - Mark the current rootfs as initramfs.
  198. */
  199. void ipe_unpack_initramfs(void)
  200. {
  201. ipe_sb(current->fs->root.mnt->mnt_sb)->initramfs = true;
  202. }
  203. #ifdef CONFIG_IPE_PROP_DM_VERITY
  204. /**
  205. * ipe_bdev_free_security() - Free IPE's LSM blob of block_devices.
  206. * @bdev: Supplies a pointer to a block_device that contains the structure
  207. * to free.
  208. */
  209. void ipe_bdev_free_security(struct block_device *bdev)
  210. {
  211. struct ipe_bdev *blob = ipe_bdev(bdev);
  212. ipe_digest_free(blob->root_hash);
  213. }
  214. #ifdef CONFIG_IPE_PROP_DM_VERITY_SIGNATURE
  215. static void ipe_set_dmverity_signature(struct ipe_bdev *blob,
  216. const void *value,
  217. size_t size)
  218. {
  219. blob->dm_verity_signed = size > 0 && value;
  220. }
  221. #else
  222. static inline void ipe_set_dmverity_signature(struct ipe_bdev *blob,
  223. const void *value,
  224. size_t size)
  225. {
  226. }
  227. #endif /* CONFIG_IPE_PROP_DM_VERITY_SIGNATURE */
  228. /**
  229. * ipe_bdev_setintegrity() - Save integrity data from a bdev to IPE's LSM blob.
  230. * @bdev: Supplies a pointer to a block_device that contains the LSM blob.
  231. * @type: Supplies the integrity type.
  232. * @value: Supplies the value to store.
  233. * @size: The size of @value.
  234. *
  235. * This hook is currently used to save dm-verity's root hash or the existence
  236. * of a validated signed dm-verity root hash into LSM blob.
  237. *
  238. * Return: %0 on success. If an error occurs, the function will return the
  239. * -errno.
  240. */
  241. int ipe_bdev_setintegrity(struct block_device *bdev, enum lsm_integrity_type type,
  242. const void *value, size_t size)
  243. {
  244. const struct dm_verity_digest *digest = NULL;
  245. struct ipe_bdev *blob = ipe_bdev(bdev);
  246. struct digest_info *info = NULL;
  247. if (type == LSM_INT_DMVERITY_SIG_VALID) {
  248. ipe_set_dmverity_signature(blob, value, size);
  249. return 0;
  250. }
  251. if (type != LSM_INT_DMVERITY_ROOTHASH)
  252. return -EINVAL;
  253. if (!value) {
  254. ipe_digest_free(blob->root_hash);
  255. blob->root_hash = NULL;
  256. return 0;
  257. }
  258. digest = value;
  259. info = kzalloc_obj(*info);
  260. if (!info)
  261. return -ENOMEM;
  262. info->digest = kmemdup(digest->digest, digest->digest_len, GFP_KERNEL);
  263. if (!info->digest)
  264. goto err;
  265. info->alg = kstrdup(digest->alg, GFP_KERNEL);
  266. if (!info->alg)
  267. goto err;
  268. info->digest_len = digest->digest_len;
  269. ipe_digest_free(blob->root_hash);
  270. blob->root_hash = info;
  271. return 0;
  272. err:
  273. ipe_digest_free(info);
  274. return -ENOMEM;
  275. }
  276. #endif /* CONFIG_IPE_PROP_DM_VERITY */
  277. #ifdef CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG
  278. /**
  279. * ipe_inode_setintegrity() - save integrity data from a inode to IPE's LSM blob.
  280. * @inode: The inode to source the security blob from.
  281. * @type: Supplies the integrity type.
  282. * @value: The value to be stored.
  283. * @size: The size of @value.
  284. *
  285. * This hook is currently used to save the existence of a validated fs-verity
  286. * builtin signature into LSM blob.
  287. *
  288. * Return: %0 on success. If an error occurs, the function will return the
  289. * -errno.
  290. */
  291. int ipe_inode_setintegrity(const struct inode *inode,
  292. enum lsm_integrity_type type,
  293. const void *value, size_t size)
  294. {
  295. struct ipe_inode *inode_sec = ipe_inode(inode);
  296. if (type == LSM_INT_FSVERITY_BUILTINSIG_VALID) {
  297. inode_sec->fs_verity_signed = size > 0 && value;
  298. return 0;
  299. }
  300. return -EINVAL;
  301. }
  302. #endif /* CONFIG_IPE_PROP_FS_VERITY_BUILTIN_SIG */