context.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  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_get_task_profile - Get another task's profile
  67. * @task: task to query (NOT NULL)
  68. *
  69. * Returns: counted reference to @task's profile
  70. */
  71. struct aa_profile *aa_get_task_profile(struct task_struct *task)
  72. {
  73. struct aa_profile *p;
  74. rcu_read_lock();
  75. p = aa_get_profile(__aa_task_profile(task));
  76. rcu_read_unlock();
  77. return p;
  78. }
  79. /**
  80. * aa_replace_current_profile - replace the current tasks profiles
  81. * @profile: new profile (NOT NULL)
  82. *
  83. * Returns: 0 or error on failure
  84. */
  85. int aa_replace_current_profile(struct aa_profile *profile)
  86. {
  87. struct aa_task_cxt *cxt = current_cxt();
  88. struct cred *new;
  89. BUG_ON(!profile);
  90. if (cxt->profile == profile)
  91. return 0;
  92. new = prepare_creds();
  93. if (!new)
  94. return -ENOMEM;
  95. cxt = cred_cxt(new);
  96. if (unconfined(profile) || (cxt->profile->ns != profile->ns))
  97. /* if switching to unconfined or a different profile namespace
  98. * clear out context state
  99. */
  100. aa_clear_task_cxt_trans(cxt);
  101. /* be careful switching cxt->profile, when racing replacement it
  102. * is possible that cxt->profile->replacedby->profile is the reference
  103. * keeping @profile valid, so make sure to get its reference before
  104. * dropping the reference on cxt->profile */
  105. aa_get_profile(profile);
  106. aa_put_profile(cxt->profile);
  107. cxt->profile = profile;
  108. commit_creds(new);
  109. return 0;
  110. }
  111. /**
  112. * aa_set_current_onexec - set the tasks change_profile to happen onexec
  113. * @profile: system profile to set at exec (MAYBE NULL to clear value)
  114. *
  115. * Returns: 0 or error on failure
  116. */
  117. int aa_set_current_onexec(struct aa_profile *profile)
  118. {
  119. struct aa_task_cxt *cxt;
  120. struct cred *new = prepare_creds();
  121. if (!new)
  122. return -ENOMEM;
  123. cxt = cred_cxt(new);
  124. aa_get_profile(profile);
  125. aa_put_profile(cxt->onexec);
  126. cxt->onexec = profile;
  127. commit_creds(new);
  128. return 0;
  129. }
  130. /**
  131. * aa_set_current_hat - set the current tasks hat
  132. * @profile: profile to set as the current hat (NOT NULL)
  133. * @token: token value that must be specified to change from the hat
  134. *
  135. * Do switch of tasks hat. If the task is currently in a hat
  136. * validate the token to match.
  137. *
  138. * Returns: 0 or error on failure
  139. */
  140. int aa_set_current_hat(struct aa_profile *profile, u64 token)
  141. {
  142. struct aa_task_cxt *cxt;
  143. struct cred *new = prepare_creds();
  144. if (!new)
  145. return -ENOMEM;
  146. BUG_ON(!profile);
  147. cxt = cred_cxt(new);
  148. if (!cxt->previous) {
  149. /* transfer refcount */
  150. cxt->previous = cxt->profile;
  151. cxt->token = token;
  152. } else if (cxt->token == token) {
  153. aa_put_profile(cxt->profile);
  154. } else {
  155. /* previous_profile && cxt->token != token */
  156. abort_creds(new);
  157. return -EACCES;
  158. }
  159. cxt->profile = aa_get_newest_profile(profile);
  160. /* clear exec on switching context */
  161. aa_put_profile(cxt->onexec);
  162. cxt->onexec = NULL;
  163. commit_creds(new);
  164. return 0;
  165. }
  166. /**
  167. * aa_restore_previous_profile - exit from hat context restoring the profile
  168. * @token: the token that must be matched to exit hat context
  169. *
  170. * Attempt to return out of a hat to the previous profile. The token
  171. * must match the stored token value.
  172. *
  173. * Returns: 0 or error of failure
  174. */
  175. int aa_restore_previous_profile(u64 token)
  176. {
  177. struct aa_task_cxt *cxt;
  178. struct cred *new = prepare_creds();
  179. if (!new)
  180. return -ENOMEM;
  181. cxt = cred_cxt(new);
  182. if (cxt->token != token) {
  183. abort_creds(new);
  184. return -EACCES;
  185. }
  186. /* ignore restores when there is no saved profile */
  187. if (!cxt->previous) {
  188. abort_creds(new);
  189. return 0;
  190. }
  191. aa_put_profile(cxt->profile);
  192. cxt->profile = aa_get_newest_profile(cxt->previous);
  193. BUG_ON(!cxt->profile);
  194. /* clear exec && prev information when restoring to previous context */
  195. aa_clear_task_cxt_trans(cxt);
  196. commit_creds(new);
  197. return 0;
  198. }