context.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. /*
  2. * AppArmor security module
  3. *
  4. * This file contains AppArmor functions used to manipulate object security
  5. * contexts.
  6. *
  7. * Copyright (C) 1998-2008 Novell/SUSE
  8. * Copyright 2009-2010 Canonical Ltd.
  9. *
  10. * This program is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU General Public License as
  12. * published by the Free Software Foundation, version 2 of the
  13. * License.
  14. *
  15. *
  16. * AppArmor sets confinement on every task, via the the aa_task_cxt and
  17. * the aa_task_cxt.profile, both of which are required and are not allowed
  18. * to be NULL. The aa_task_cxt is not reference counted and is unique
  19. * to each cred (which is reference count). The profile pointed to by
  20. * the task_cxt is reference counted.
  21. *
  22. * TODO
  23. * If a task uses change_hat it currently does not return to the old
  24. * cred or task context but instead creates a new one. Ideally the task
  25. * should return to the previous cred if it has not been modified.
  26. *
  27. */
  28. #include "include/context.h"
  29. #include "include/policy.h"
  30. /**
  31. * aa_alloc_task_context - allocate a new task_cxt
  32. * @flags: gfp flags for allocation
  33. *
  34. * Returns: allocated buffer or NULL on failure
  35. */
  36. struct aa_task_cxt *aa_alloc_task_context(gfp_t flags)
  37. {
  38. return kzalloc(sizeof(struct aa_task_cxt), flags);
  39. }
  40. /**
  41. * aa_free_task_context - free a task_cxt
  42. * @cxt: task_cxt to free (MAYBE NULL)
  43. */
  44. void aa_free_task_context(struct aa_task_cxt *cxt)
  45. {
  46. if (cxt) {
  47. aa_put_profile(cxt->profile);
  48. aa_put_profile(cxt->previous);
  49. aa_put_profile(cxt->onexec);
  50. kzfree(cxt);
  51. }
  52. }
  53. /**
  54. * aa_dup_task_context - duplicate a task context, incrementing reference counts
  55. * @new: a blank task context (NOT NULL)
  56. * @old: the task context to copy (NOT NULL)
  57. */
  58. void aa_dup_task_context(struct aa_task_cxt *new, const struct aa_task_cxt *old)
  59. {
  60. *new = *old;
  61. aa_get_profile(new->profile);
  62. aa_get_profile(new->previous);
  63. aa_get_profile(new->onexec);
  64. }
  65. /**
  66. * aa_replace_current_profile - replace the current tasks profiles
  67. * @profile: new profile (NOT NULL)
  68. *
  69. * Returns: 0 or error on failure
  70. */
  71. int aa_replace_current_profile(struct aa_profile *profile)
  72. {
  73. struct aa_task_cxt *cxt = current_cred()->security;
  74. struct cred *new;
  75. BUG_ON(!profile);
  76. if (cxt->profile == profile)
  77. return 0;
  78. new = prepare_creds();
  79. if (!new)
  80. return -ENOMEM;
  81. cxt = new->security;
  82. if (unconfined(profile) || (cxt->profile->ns != profile->ns)) {
  83. /* if switching to unconfined or a different profile namespace
  84. * clear out context state
  85. */
  86. aa_put_profile(cxt->previous);
  87. aa_put_profile(cxt->onexec);
  88. cxt->previous = NULL;
  89. cxt->onexec = NULL;
  90. cxt->token = 0;
  91. }
  92. /* be careful switching cxt->profile, when racing replacement it
  93. * is possible that cxt->profile->replacedby is the reference keeping
  94. * @profile valid, so make sure to get its reference before dropping
  95. * the reference on cxt->profile */
  96. aa_get_profile(profile);
  97. aa_put_profile(cxt->profile);
  98. cxt->profile = profile;
  99. commit_creds(new);
  100. return 0;
  101. }
  102. /**
  103. * aa_set_current_onexec - set the tasks change_profile to happen onexec
  104. * @profile: system profile to set at exec (MAYBE NULL to clear value)
  105. *
  106. * Returns: 0 or error on failure
  107. */
  108. int aa_set_current_onexec(struct aa_profile *profile)
  109. {
  110. struct aa_task_cxt *cxt;
  111. struct cred *new = prepare_creds();
  112. if (!new)
  113. return -ENOMEM;
  114. cxt = new->security;
  115. aa_get_profile(profile);
  116. aa_put_profile(cxt->onexec);
  117. cxt->onexec = profile;
  118. commit_creds(new);
  119. return 0;
  120. }
  121. /**
  122. * aa_set_current_hat - set the current tasks hat
  123. * @profile: profile to set as the current hat (NOT NULL)
  124. * @token: token value that must be specified to change from the hat
  125. *
  126. * Do switch of tasks hat. If the task is currently in a hat
  127. * validate the token to match.
  128. *
  129. * Returns: 0 or error on failure
  130. */
  131. int aa_set_current_hat(struct aa_profile *profile, u64 token)
  132. {
  133. struct aa_task_cxt *cxt;
  134. struct cred *new = prepare_creds();
  135. if (!new)
  136. return -ENOMEM;
  137. BUG_ON(!profile);
  138. cxt = new->security;
  139. if (!cxt->previous) {
  140. /* transfer refcount */
  141. cxt->previous = cxt->profile;
  142. cxt->token = token;
  143. } else if (cxt->token == token) {
  144. aa_put_profile(cxt->profile);
  145. } else {
  146. /* previous_profile && cxt->token != token */
  147. abort_creds(new);
  148. return -EACCES;
  149. }
  150. cxt->profile = aa_get_profile(aa_newest_version(profile));
  151. /* clear exec on switching context */
  152. aa_put_profile(cxt->onexec);
  153. cxt->onexec = NULL;
  154. commit_creds(new);
  155. return 0;
  156. }
  157. /**
  158. * aa_restore_previous_profile - exit from hat context restoring the profile
  159. * @token: the token that must be matched to exit hat context
  160. *
  161. * Attempt to return out of a hat to the previous profile. The token
  162. * must match the stored token value.
  163. *
  164. * Returns: 0 or error of failure
  165. */
  166. int aa_restore_previous_profile(u64 token)
  167. {
  168. struct aa_task_cxt *cxt;
  169. struct cred *new = prepare_creds();
  170. if (!new)
  171. return -ENOMEM;
  172. cxt = new->security;
  173. if (cxt->token != token) {
  174. abort_creds(new);
  175. return -EACCES;
  176. }
  177. /* ignore restores when there is no saved profile */
  178. if (!cxt->previous) {
  179. abort_creds(new);
  180. return 0;
  181. }
  182. aa_put_profile(cxt->profile);
  183. cxt->profile = aa_newest_version(cxt->previous);
  184. BUG_ON(!cxt->profile);
  185. if (unlikely(cxt->profile != cxt->previous)) {
  186. aa_get_profile(cxt->profile);
  187. aa_put_profile(cxt->previous);
  188. }
  189. /* clear exec && prev information when restoring to previous context */
  190. cxt->previous = NULL;
  191. cxt->token = 0;
  192. aa_put_profile(cxt->onexec);
  193. cxt->onexec = NULL;
  194. commit_creds(new);
  195. return 0;
  196. }