context.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  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_cred()->security;
  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 = new->security;
  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_put_profile(cxt->previous);
  101. aa_put_profile(cxt->onexec);
  102. cxt->previous = NULL;
  103. cxt->onexec = NULL;
  104. cxt->token = 0;
  105. }
  106. /* be careful switching cxt->profile, when racing replacement it
  107. * is possible that cxt->profile->replacedby is the reference keeping
  108. * @profile valid, so make sure to get its reference before dropping
  109. * the reference on cxt->profile */
  110. aa_get_profile(profile);
  111. aa_put_profile(cxt->profile);
  112. cxt->profile = profile;
  113. commit_creds(new);
  114. return 0;
  115. }
  116. /**
  117. * aa_set_current_onexec - set the tasks change_profile to happen onexec
  118. * @profile: system profile to set at exec (MAYBE NULL to clear value)
  119. *
  120. * Returns: 0 or error on failure
  121. */
  122. int aa_set_current_onexec(struct aa_profile *profile)
  123. {
  124. struct aa_task_cxt *cxt;
  125. struct cred *new = prepare_creds();
  126. if (!new)
  127. return -ENOMEM;
  128. cxt = new->security;
  129. aa_get_profile(profile);
  130. aa_put_profile(cxt->onexec);
  131. cxt->onexec = profile;
  132. commit_creds(new);
  133. return 0;
  134. }
  135. /**
  136. * aa_set_current_hat - set the current tasks hat
  137. * @profile: profile to set as the current hat (NOT NULL)
  138. * @token: token value that must be specified to change from the hat
  139. *
  140. * Do switch of tasks hat. If the task is currently in a hat
  141. * validate the token to match.
  142. *
  143. * Returns: 0 or error on failure
  144. */
  145. int aa_set_current_hat(struct aa_profile *profile, u64 token)
  146. {
  147. struct aa_task_cxt *cxt;
  148. struct cred *new = prepare_creds();
  149. if (!new)
  150. return -ENOMEM;
  151. BUG_ON(!profile);
  152. cxt = new->security;
  153. if (!cxt->previous) {
  154. /* transfer refcount */
  155. cxt->previous = cxt->profile;
  156. cxt->token = token;
  157. } else if (cxt->token == token) {
  158. aa_put_profile(cxt->profile);
  159. } else {
  160. /* previous_profile && cxt->token != token */
  161. abort_creds(new);
  162. return -EACCES;
  163. }
  164. cxt->profile = aa_get_profile(aa_newest_version(profile));
  165. /* clear exec on switching context */
  166. aa_put_profile(cxt->onexec);
  167. cxt->onexec = NULL;
  168. commit_creds(new);
  169. return 0;
  170. }
  171. /**
  172. * aa_restore_previous_profile - exit from hat context restoring the profile
  173. * @token: the token that must be matched to exit hat context
  174. *
  175. * Attempt to return out of a hat to the previous profile. The token
  176. * must match the stored token value.
  177. *
  178. * Returns: 0 or error of failure
  179. */
  180. int aa_restore_previous_profile(u64 token)
  181. {
  182. struct aa_task_cxt *cxt;
  183. struct cred *new = prepare_creds();
  184. if (!new)
  185. return -ENOMEM;
  186. cxt = new->security;
  187. if (cxt->token != token) {
  188. abort_creds(new);
  189. return -EACCES;
  190. }
  191. /* ignore restores when there is no saved profile */
  192. if (!cxt->previous) {
  193. abort_creds(new);
  194. return 0;
  195. }
  196. aa_put_profile(cxt->profile);
  197. cxt->profile = aa_newest_version(cxt->previous);
  198. BUG_ON(!cxt->profile);
  199. if (unlikely(cxt->profile != cxt->previous)) {
  200. aa_get_profile(cxt->profile);
  201. aa_put_profile(cxt->previous);
  202. }
  203. /* clear exec && prev information when restoring to previous context */
  204. cxt->previous = NULL;
  205. cxt->token = 0;
  206. aa_put_profile(cxt->onexec);
  207. cxt->onexec = NULL;
  208. commit_creds(new);
  209. return 0;
  210. }