context.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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_ctx and
  17. * the aa_task_ctx.label, both of which are required and are not allowed
  18. * to be NULL. The aa_task_ctx is not reference counted and is unique
  19. * to each cred (which is reference count). The label pointed to by
  20. * the task_ctx 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_ctx
  32. * @flags: gfp flags for allocation
  33. *
  34. * Returns: allocated buffer or NULL on failure
  35. */
  36. struct aa_task_ctx *aa_alloc_task_context(gfp_t flags)
  37. {
  38. return kzalloc(sizeof(struct aa_task_ctx), flags);
  39. }
  40. /**
  41. * aa_free_task_context - free a task_ctx
  42. * @ctx: task_ctx to free (MAYBE NULL)
  43. */
  44. void aa_free_task_context(struct aa_task_ctx *ctx)
  45. {
  46. if (ctx) {
  47. aa_put_label(ctx->label);
  48. aa_put_label(ctx->previous);
  49. aa_put_label(ctx->onexec);
  50. kzfree(ctx);
  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_ctx *new, const struct aa_task_ctx *old)
  59. {
  60. *new = *old;
  61. aa_get_label(new->label);
  62. aa_get_label(new->previous);
  63. aa_get_label(new->onexec);
  64. }
  65. /**
  66. * aa_get_task_label - Get another task's label
  67. * @task: task to query (NOT NULL)
  68. *
  69. * Returns: counted reference to @task's label
  70. */
  71. struct aa_label *aa_get_task_label(struct task_struct *task)
  72. {
  73. struct aa_label *p;
  74. rcu_read_lock();
  75. p = aa_get_newest_label(__aa_task_raw_label(task));
  76. rcu_read_unlock();
  77. return p;
  78. }
  79. /**
  80. * aa_replace_current_label - replace the current tasks label
  81. * @label: new label (NOT NULL)
  82. *
  83. * Returns: 0 or error on failure
  84. */
  85. int aa_replace_current_label(struct aa_label *label)
  86. {
  87. struct aa_task_ctx *ctx = current_ctx();
  88. struct cred *new;
  89. AA_BUG(!label);
  90. if (ctx->label == label)
  91. return 0;
  92. if (current_cred() != current_real_cred())
  93. return -EBUSY;
  94. new = prepare_creds();
  95. if (!new)
  96. return -ENOMEM;
  97. ctx = cred_ctx(new);
  98. if (unconfined(label) || (labels_ns(ctx->label) != labels_ns(label)))
  99. /* if switching to unconfined or a different label namespace
  100. * clear out context state
  101. */
  102. aa_clear_task_ctx_trans(ctx);
  103. /*
  104. * be careful switching ctx->profile, when racing replacement it
  105. * is possible that ctx->profile->proxy->profile is the reference
  106. * keeping @profile valid, so make sure to get its reference before
  107. * dropping the reference on ctx->profile
  108. */
  109. aa_get_label(label);
  110. aa_put_label(ctx->label);
  111. ctx->label = label;
  112. commit_creds(new);
  113. return 0;
  114. }
  115. /**
  116. * aa_set_current_onexec - set the tasks change_profile to happen onexec
  117. * @label: system label to set at exec (MAYBE NULL to clear value)
  118. * @stack: whether stacking should be done
  119. * Returns: 0 or error on failure
  120. */
  121. int aa_set_current_onexec(struct aa_label *label, bool stack)
  122. {
  123. struct aa_task_ctx *ctx;
  124. struct cred *new = prepare_creds();
  125. if (!new)
  126. return -ENOMEM;
  127. ctx = cred_ctx(new);
  128. aa_get_label(label);
  129. aa_clear_task_ctx_trans(ctx);
  130. ctx->onexec = label;
  131. ctx->token = stack;
  132. commit_creds(new);
  133. return 0;
  134. }
  135. /**
  136. * aa_set_current_hat - set the current tasks hat
  137. * @label: label 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_label *label, u64 token)
  146. {
  147. struct aa_task_ctx *ctx;
  148. struct cred *new = prepare_creds();
  149. if (!new)
  150. return -ENOMEM;
  151. AA_BUG(!label);
  152. ctx = cred_ctx(new);
  153. if (!ctx->previous) {
  154. /* transfer refcount */
  155. ctx->previous = ctx->label;
  156. ctx->token = token;
  157. } else if (ctx->token == token) {
  158. aa_put_label(ctx->label);
  159. } else {
  160. /* previous_profile && ctx->token != token */
  161. abort_creds(new);
  162. return -EACCES;
  163. }
  164. ctx->label = aa_get_newest_label(label);
  165. /* clear exec on switching context */
  166. aa_put_label(ctx->onexec);
  167. ctx->onexec = NULL;
  168. commit_creds(new);
  169. return 0;
  170. }
  171. /**
  172. * aa_restore_previous_label - exit from hat context restoring previous label
  173. * @token: the token that must be matched to exit hat context
  174. *
  175. * Attempt to return out of a hat to the previous label. The token
  176. * must match the stored token value.
  177. *
  178. * Returns: 0 or error of failure
  179. */
  180. int aa_restore_previous_label(u64 token)
  181. {
  182. struct aa_task_ctx *ctx;
  183. struct cred *new = prepare_creds();
  184. if (!new)
  185. return -ENOMEM;
  186. ctx = cred_ctx(new);
  187. if (ctx->token != token) {
  188. abort_creds(new);
  189. return -EACCES;
  190. }
  191. /* ignore restores when there is no saved label */
  192. if (!ctx->previous) {
  193. abort_creds(new);
  194. return 0;
  195. }
  196. aa_put_label(ctx->label);
  197. ctx->label = aa_get_newest_label(ctx->previous);
  198. AA_BUG(!ctx->label);
  199. /* clear exec && prev information when restoring to previous context */
  200. aa_clear_task_ctx_trans(ctx);
  201. commit_creds(new);
  202. return 0;
  203. }