task.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * AppArmor security module
  4. *
  5. * This file contains AppArmor task related definitions and mediation
  6. *
  7. * Copyright 2017 Canonical Ltd.
  8. *
  9. * TODO
  10. * If a task uses change_hat it currently does not return to the old
  11. * cred or task context but instead creates a new one. Ideally the task
  12. * should return to the previous cred if it has not been modified.
  13. */
  14. #include <linux/gfp.h>
  15. #include <linux/ptrace.h>
  16. #include "include/audit.h"
  17. #include "include/cred.h"
  18. #include "include/policy.h"
  19. #include "include/task.h"
  20. /**
  21. * aa_get_task_label - Get another task's label
  22. * @task: task to query (NOT NULL)
  23. *
  24. * Returns: counted reference to @task's label
  25. */
  26. struct aa_label *aa_get_task_label(struct task_struct *task)
  27. {
  28. struct aa_label *p;
  29. rcu_read_lock();
  30. p = aa_get_newest_label(__aa_task_raw_label(task));
  31. rcu_read_unlock();
  32. return p;
  33. }
  34. /**
  35. * aa_replace_current_label - replace the current tasks label
  36. * @label: new label (NOT NULL)
  37. *
  38. * Returns: 0 or error on failure
  39. */
  40. int aa_replace_current_label(struct aa_label *label)
  41. {
  42. struct aa_label *old = aa_current_raw_label();
  43. struct aa_task_ctx *ctx = task_ctx(current);
  44. struct cred *new;
  45. AA_BUG(!label);
  46. if (old == label)
  47. return 0;
  48. if (current_cred() != current_real_cred())
  49. return -EBUSY;
  50. new = prepare_creds();
  51. if (!new)
  52. return -ENOMEM;
  53. if (ctx->nnp && label_is_stale(ctx->nnp)) {
  54. struct aa_label *tmp = ctx->nnp;
  55. ctx->nnp = aa_get_newest_label(tmp);
  56. aa_put_label(tmp);
  57. }
  58. if (unconfined(label) || (labels_ns(old) != labels_ns(label)))
  59. /*
  60. * if switching to unconfined or a different label namespace
  61. * clear out context state
  62. */
  63. aa_clear_task_ctx_trans(task_ctx(current));
  64. /*
  65. * be careful switching cred label, when racing replacement it
  66. * is possible that the cred labels's->proxy->label is the reference
  67. * keeping @label valid, so make sure to get its reference before
  68. * dropping the reference on the cred's label
  69. */
  70. aa_get_label(label);
  71. aa_put_label(cred_label(new));
  72. set_cred_label(new, label);
  73. commit_creds(new);
  74. return 0;
  75. }
  76. /**
  77. * aa_set_current_onexec - set the tasks change_profile to happen onexec
  78. * @label: system label to set at exec (MAYBE NULL to clear value)
  79. * @stack: whether stacking should be done
  80. * Returns: 0 or error on failure
  81. */
  82. int aa_set_current_onexec(struct aa_label *label, bool stack)
  83. {
  84. struct aa_task_ctx *ctx = task_ctx(current);
  85. aa_get_label(label);
  86. aa_put_label(ctx->onexec);
  87. ctx->onexec = label;
  88. ctx->token = stack;
  89. return 0;
  90. }
  91. /**
  92. * aa_set_current_hat - set the current tasks hat
  93. * @label: label to set as the current hat (NOT NULL)
  94. * @token: token value that must be specified to change from the hat
  95. *
  96. * Do switch of tasks hat. If the task is currently in a hat
  97. * validate the token to match.
  98. *
  99. * Returns: 0 or error on failure
  100. */
  101. int aa_set_current_hat(struct aa_label *label, u64 token)
  102. {
  103. struct aa_task_ctx *ctx = task_ctx(current);
  104. struct cred *new;
  105. new = prepare_creds();
  106. if (!new)
  107. return -ENOMEM;
  108. AA_BUG(!label);
  109. if (!ctx->previous) {
  110. /* transfer refcount */
  111. ctx->previous = cred_label(new);
  112. ctx->token = token;
  113. } else if (ctx->token == token) {
  114. aa_put_label(cred_label(new));
  115. } else {
  116. /* previous_profile && ctx->token != token */
  117. abort_creds(new);
  118. return -EACCES;
  119. }
  120. set_cred_label(new, aa_get_newest_label(label));
  121. /* clear exec on switching context */
  122. aa_put_label(ctx->onexec);
  123. ctx->onexec = NULL;
  124. commit_creds(new);
  125. return 0;
  126. }
  127. /**
  128. * aa_restore_previous_label - exit from hat context restoring previous label
  129. * @token: the token that must be matched to exit hat context
  130. *
  131. * Attempt to return out of a hat to the previous label. The token
  132. * must match the stored token value.
  133. *
  134. * Returns: 0 or error of failure
  135. */
  136. int aa_restore_previous_label(u64 token)
  137. {
  138. struct aa_task_ctx *ctx = task_ctx(current);
  139. struct cred *new;
  140. if (ctx->token != token)
  141. return -EACCES;
  142. /* ignore restores when there is no saved label */
  143. if (!ctx->previous)
  144. return 0;
  145. new = prepare_creds();
  146. if (!new)
  147. return -ENOMEM;
  148. aa_put_label(cred_label(new));
  149. set_cred_label(new, aa_get_newest_label(ctx->previous));
  150. AA_BUG(!cred_label(new));
  151. /* clear exec && prev information when restoring to previous context */
  152. aa_clear_task_ctx_trans(ctx);
  153. commit_creds(new);
  154. return 0;
  155. }
  156. /**
  157. * audit_ptrace_mask - convert mask to permission string
  158. * @mask: permission mask to convert
  159. *
  160. * Returns: pointer to static string
  161. */
  162. static const char *audit_ptrace_mask(u32 mask)
  163. {
  164. switch (mask) {
  165. case MAY_READ:
  166. return "read";
  167. case MAY_WRITE:
  168. return "trace";
  169. case AA_MAY_BE_READ:
  170. return "readby";
  171. case AA_MAY_BE_TRACED:
  172. return "tracedby";
  173. }
  174. return "";
  175. }
  176. /* call back to audit ptrace fields */
  177. static void audit_ptrace_cb(struct audit_buffer *ab, void *va)
  178. {
  179. struct common_audit_data *sa = va;
  180. if (aad(sa)->request & AA_PTRACE_PERM_MASK) {
  181. audit_log_format(ab, " requested_mask=\"%s\"",
  182. audit_ptrace_mask(aad(sa)->request));
  183. if (aad(sa)->denied & AA_PTRACE_PERM_MASK) {
  184. audit_log_format(ab, " denied_mask=\"%s\"",
  185. audit_ptrace_mask(aad(sa)->denied));
  186. }
  187. }
  188. audit_log_format(ab, " peer=");
  189. aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
  190. FLAGS_NONE, GFP_ATOMIC);
  191. }
  192. /* assumes check for PROFILE_MEDIATES is already done */
  193. /* TODO: conditionals */
  194. static int profile_ptrace_perm(struct aa_profile *profile,
  195. struct aa_label *peer, u32 request,
  196. struct common_audit_data *sa)
  197. {
  198. struct aa_perms perms = { };
  199. aad(sa)->peer = peer;
  200. aa_profile_match_label(profile, peer, AA_CLASS_PTRACE, request,
  201. &perms);
  202. aa_apply_modes_to_perms(profile, &perms);
  203. return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb);
  204. }
  205. static int profile_tracee_perm(struct aa_profile *tracee,
  206. struct aa_label *tracer, u32 request,
  207. struct common_audit_data *sa)
  208. {
  209. if (profile_unconfined(tracee) || unconfined(tracer) ||
  210. !PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE))
  211. return 0;
  212. return profile_ptrace_perm(tracee, tracer, request, sa);
  213. }
  214. static int profile_tracer_perm(struct aa_profile *tracer,
  215. struct aa_label *tracee, u32 request,
  216. struct common_audit_data *sa)
  217. {
  218. if (profile_unconfined(tracer))
  219. return 0;
  220. if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE))
  221. return profile_ptrace_perm(tracer, tracee, request, sa);
  222. /* profile uses the old style capability check for ptrace */
  223. if (&tracer->label == tracee)
  224. return 0;
  225. aad(sa)->label = &tracer->label;
  226. aad(sa)->peer = tracee;
  227. aad(sa)->request = 0;
  228. aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE,
  229. CAP_OPT_NONE);
  230. return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb);
  231. }
  232. /**
  233. * aa_may_ptrace - test if tracer task can trace the tracee
  234. * @tracer: label of the task doing the tracing (NOT NULL)
  235. * @tracee: task label to be traced
  236. * @request: permission request
  237. *
  238. * Returns: %0 else error code if permission denied or error
  239. */
  240. int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee,
  241. u32 request)
  242. {
  243. struct aa_profile *profile;
  244. u32 xrequest = request << PTRACE_PERM_SHIFT;
  245. DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE);
  246. return xcheck_labels(tracer, tracee, profile,
  247. profile_tracer_perm(profile, tracee, request, &sa),
  248. profile_tracee_perm(profile, tracer, xrequest, &sa));
  249. }