policy.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2020-2024 Microsoft Corporation. All rights reserved.
  4. */
  5. #include <linux/errno.h>
  6. #include <linux/verification.h>
  7. #include "ipe.h"
  8. #include "eval.h"
  9. #include "fs.h"
  10. #include "policy.h"
  11. #include "policy_parser.h"
  12. #include "audit.h"
  13. /* lock for synchronizing writers across ipe policy */
  14. DEFINE_MUTEX(ipe_policy_lock);
  15. /**
  16. * ver_to_u64() - Convert an internal ipe_policy_version to a u64.
  17. * @p: Policy to extract the version from.
  18. *
  19. * Bits (LSB is index 0):
  20. * [48,32] -> Major
  21. * [32,16] -> Minor
  22. * [16, 0] -> Revision
  23. *
  24. * Return: u64 version of the embedded version structure.
  25. */
  26. static inline u64 ver_to_u64(const struct ipe_policy *const p)
  27. {
  28. u64 r;
  29. r = (((u64)p->parsed->version.major) << 32)
  30. | (((u64)p->parsed->version.minor) << 16)
  31. | ((u64)(p->parsed->version.rev));
  32. return r;
  33. }
  34. /**
  35. * ipe_free_policy() - Deallocate a given IPE policy.
  36. * @p: Supplies the policy to free.
  37. *
  38. * Safe to call on IS_ERR/NULL.
  39. */
  40. void ipe_free_policy(struct ipe_policy *p)
  41. {
  42. if (IS_ERR_OR_NULL(p))
  43. return;
  44. ipe_del_policyfs_node(p);
  45. ipe_free_parsed_policy(p->parsed);
  46. /*
  47. * p->text is allocated only when p->pkcs7 is not NULL
  48. * otherwise it points to the plaintext data inside the pkcs7
  49. */
  50. if (!p->pkcs7)
  51. kfree(p->text);
  52. kfree(p->pkcs7);
  53. kfree(p);
  54. }
  55. static int set_pkcs7_data(void *ctx, const void *data, size_t len,
  56. size_t asn1hdrlen __always_unused)
  57. {
  58. struct ipe_policy *p = ctx;
  59. p->text = (const char *)data;
  60. p->textlen = len;
  61. return 0;
  62. }
  63. /**
  64. * ipe_update_policy() - parse a new policy and replace old with it.
  65. * @root: Supplies a pointer to the securityfs inode saved the policy.
  66. * @text: Supplies a pointer to the plain text policy.
  67. * @textlen: Supplies the length of @text.
  68. * @pkcs7: Supplies a pointer to a buffer containing a pkcs7 message.
  69. * @pkcs7len: Supplies the length of @pkcs7len.
  70. *
  71. * @text/@textlen is mutually exclusive with @pkcs7/@pkcs7len - see
  72. * ipe_new_policy.
  73. *
  74. * Context: Requires root->i_rwsem to be held.
  75. * Return:
  76. * * %0 - Success
  77. * * %-ENOENT - Policy was deleted while updating
  78. * * %-EINVAL - Policy name mismatch
  79. * * %-ESTALE - Policy version too old
  80. */
  81. int ipe_update_policy(struct inode *root, const char *text, size_t textlen,
  82. const char *pkcs7, size_t pkcs7len)
  83. {
  84. struct ipe_policy *old, *ap, *new = NULL;
  85. int rc = 0;
  86. old = (struct ipe_policy *)root->i_private;
  87. if (!old)
  88. return -ENOENT;
  89. new = ipe_new_policy(text, textlen, pkcs7, pkcs7len);
  90. if (IS_ERR(new))
  91. return PTR_ERR(new);
  92. if (strcmp(new->parsed->name, old->parsed->name)) {
  93. rc = -EINVAL;
  94. goto err;
  95. }
  96. if (ver_to_u64(old) >= ver_to_u64(new)) {
  97. rc = -ESTALE;
  98. goto err;
  99. }
  100. root->i_private = new;
  101. swap(new->policyfs, old->policyfs);
  102. ipe_audit_policy_load(new);
  103. mutex_lock(&ipe_policy_lock);
  104. ap = rcu_dereference_protected(ipe_active_policy,
  105. lockdep_is_held(&ipe_policy_lock));
  106. if (old == ap) {
  107. rcu_assign_pointer(ipe_active_policy, new);
  108. mutex_unlock(&ipe_policy_lock);
  109. ipe_audit_policy_activation(old, new);
  110. } else {
  111. mutex_unlock(&ipe_policy_lock);
  112. }
  113. synchronize_rcu();
  114. ipe_free_policy(old);
  115. return 0;
  116. err:
  117. ipe_free_policy(new);
  118. return rc;
  119. }
  120. /**
  121. * ipe_new_policy() - Allocate and parse an ipe_policy structure.
  122. *
  123. * @text: Supplies a pointer to the plain-text policy to parse.
  124. * @textlen: Supplies the length of @text.
  125. * @pkcs7: Supplies a pointer to a pkcs7-signed IPE policy.
  126. * @pkcs7len: Supplies the length of @pkcs7.
  127. *
  128. * @text/@textlen Should be NULL/0 if @pkcs7/@pkcs7len is set.
  129. *
  130. * Return:
  131. * * a pointer to the ipe_policy structure - Success
  132. * * %-EBADMSG - Policy is invalid
  133. * * %-ENOMEM - Out of memory (OOM)
  134. * * %-ERANGE - Policy version number overflow
  135. * * %-EINVAL - Policy version parsing error
  136. * * %-ENOKEY - Policy signing key not found
  137. * * %-EKEYREJECTED - Policy signature verification failed
  138. */
  139. struct ipe_policy *ipe_new_policy(const char *text, size_t textlen,
  140. const char *pkcs7, size_t pkcs7len)
  141. {
  142. struct ipe_policy *new = NULL;
  143. int rc = 0;
  144. new = kzalloc_obj(*new);
  145. if (!new)
  146. return ERR_PTR(-ENOMEM);
  147. if (!text) {
  148. new->pkcs7len = pkcs7len;
  149. new->pkcs7 = kmemdup(pkcs7, pkcs7len, GFP_KERNEL);
  150. if (!new->pkcs7) {
  151. rc = -ENOMEM;
  152. goto err;
  153. }
  154. rc = verify_pkcs7_signature(NULL, 0, new->pkcs7, pkcs7len,
  155. #ifdef CONFIG_IPE_POLICY_SIG_SECONDARY_KEYRING
  156. VERIFY_USE_SECONDARY_KEYRING,
  157. #else
  158. NULL,
  159. #endif
  160. VERIFYING_UNSPECIFIED_SIGNATURE,
  161. set_pkcs7_data, new);
  162. #ifdef CONFIG_IPE_POLICY_SIG_PLATFORM_KEYRING
  163. if (rc == -ENOKEY || rc == -EKEYREJECTED)
  164. rc = verify_pkcs7_signature(NULL, 0, new->pkcs7, pkcs7len,
  165. VERIFY_USE_PLATFORM_KEYRING,
  166. VERIFYING_UNSPECIFIED_SIGNATURE,
  167. set_pkcs7_data, new);
  168. #endif
  169. if (rc)
  170. goto err;
  171. } else {
  172. new->textlen = textlen;
  173. new->text = kstrdup(text, GFP_KERNEL);
  174. if (!new->text) {
  175. rc = -ENOMEM;
  176. goto err;
  177. }
  178. }
  179. rc = ipe_parse_policy(new);
  180. if (rc)
  181. goto err;
  182. return new;
  183. err:
  184. ipe_free_policy(new);
  185. return ERR_PTR(rc);
  186. }
  187. /**
  188. * ipe_set_active_pol() - Make @p the active policy.
  189. * @p: Supplies a pointer to the policy to make active.
  190. *
  191. * Context: Requires root->i_rwsem, which i_private has the policy, to be held.
  192. * Return:
  193. * * %0 - Success
  194. * * %-EINVAL - New active policy version is invalid
  195. */
  196. int ipe_set_active_pol(const struct ipe_policy *p)
  197. {
  198. struct ipe_policy *ap = NULL;
  199. mutex_lock(&ipe_policy_lock);
  200. ap = rcu_dereference_protected(ipe_active_policy,
  201. lockdep_is_held(&ipe_policy_lock));
  202. if (ap == p) {
  203. mutex_unlock(&ipe_policy_lock);
  204. return 0;
  205. }
  206. if (ap && ver_to_u64(ap) > ver_to_u64(p)) {
  207. mutex_unlock(&ipe_policy_lock);
  208. return -EINVAL;
  209. }
  210. rcu_assign_pointer(ipe_active_policy, p);
  211. ipe_audit_policy_activation(ap, p);
  212. mutex_unlock(&ipe_policy_lock);
  213. return 0;
  214. }