task.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  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/path.h"
  17. #include "include/audit.h"
  18. #include "include/cred.h"
  19. #include "include/policy.h"
  20. #include "include/task.h"
  21. /**
  22. * aa_get_task_label - Get another task's label
  23. * @task: task to query (NOT NULL)
  24. *
  25. * Returns: counted reference to @task's label
  26. */
  27. struct aa_label *aa_get_task_label(struct task_struct *task)
  28. {
  29. struct aa_label *p;
  30. rcu_read_lock();
  31. p = aa_get_newest_cred_label(__task_cred(task));
  32. rcu_read_unlock();
  33. return p;
  34. }
  35. /**
  36. * aa_replace_current_label - replace the current tasks label
  37. * @label: new label (NOT NULL)
  38. *
  39. * Returns: 0 or error on failure
  40. */
  41. int aa_replace_current_label(struct aa_label *label)
  42. {
  43. struct aa_label *old = aa_current_raw_label();
  44. struct aa_task_ctx *ctx = task_ctx(current);
  45. struct cred *new;
  46. AA_BUG(!label);
  47. if (old == label)
  48. return 0;
  49. if (current_cred() != current_real_cred())
  50. return -EBUSY;
  51. new = prepare_creds();
  52. if (!new)
  53. return -ENOMEM;
  54. if (ctx->nnp && label_is_stale(ctx->nnp)) {
  55. struct aa_label *tmp = ctx->nnp;
  56. ctx->nnp = aa_get_newest_label(tmp);
  57. aa_put_label(tmp);
  58. }
  59. if (unconfined(label) || (labels_ns(old) != labels_ns(label)))
  60. /*
  61. * if switching to unconfined or a different label namespace
  62. * clear out context state
  63. */
  64. aa_clear_task_ctx_trans(task_ctx(current));
  65. /*
  66. * be careful switching cred label, when racing replacement it
  67. * is possible that the cred labels's->proxy->label is the reference
  68. * keeping @label valid, so make sure to get its reference before
  69. * dropping the reference on the cred's label
  70. */
  71. aa_get_label(label);
  72. aa_put_label(cred_label(new));
  73. set_cred_label(new, label);
  74. commit_creds(new);
  75. return 0;
  76. }
  77. /**
  78. * aa_set_current_onexec - set the tasks change_profile to happen onexec
  79. * @label: system label to set at exec (MAYBE NULL to clear value)
  80. * @stack: whether stacking should be done
  81. */
  82. void 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. }
  90. /**
  91. * aa_set_current_hat - set the current tasks hat
  92. * @label: label to set as the current hat (NOT NULL)
  93. * @token: token value that must be specified to change from the hat
  94. *
  95. * Do switch of tasks hat. If the task is currently in a hat
  96. * validate the token to match.
  97. *
  98. * Returns: 0 or error on failure
  99. */
  100. int aa_set_current_hat(struct aa_label *label, u64 token)
  101. {
  102. struct aa_task_ctx *ctx = task_ctx(current);
  103. struct cred *new;
  104. new = prepare_creds();
  105. if (!new)
  106. return -ENOMEM;
  107. AA_BUG(!label);
  108. if (!ctx->previous) {
  109. /* transfer refcount */
  110. ctx->previous = cred_label(new);
  111. ctx->token = token;
  112. } else if (ctx->token == token) {
  113. aa_put_label(cred_label(new));
  114. } else {
  115. /* previous_profile && ctx->token != token */
  116. abort_creds(new);
  117. return -EACCES;
  118. }
  119. set_cred_label(new, aa_get_newest_label(label));
  120. /* clear exec on switching context */
  121. aa_put_label(ctx->onexec);
  122. ctx->onexec = NULL;
  123. commit_creds(new);
  124. return 0;
  125. }
  126. /**
  127. * aa_restore_previous_label - exit from hat context restoring previous label
  128. * @token: the token that must be matched to exit hat context
  129. *
  130. * Attempt to return out of a hat to the previous label. The token
  131. * must match the stored token value.
  132. *
  133. * Returns: 0 or error of failure
  134. */
  135. int aa_restore_previous_label(u64 token)
  136. {
  137. struct aa_task_ctx *ctx = task_ctx(current);
  138. struct cred *new;
  139. if (ctx->token != token)
  140. return -EACCES;
  141. /* ignore restores when there is no saved label */
  142. if (!ctx->previous)
  143. return 0;
  144. new = prepare_creds();
  145. if (!new)
  146. return -ENOMEM;
  147. aa_put_label(cred_label(new));
  148. set_cred_label(new, aa_get_newest_label(ctx->previous));
  149. AA_BUG(!cred_label(new));
  150. /* clear exec && prev information when restoring to previous context */
  151. aa_clear_task_ctx_trans(ctx);
  152. commit_creds(new);
  153. return 0;
  154. }
  155. /**
  156. * audit_ptrace_mask - convert mask to permission string
  157. * @mask: permission mask to convert
  158. *
  159. * Returns: pointer to static string
  160. */
  161. static const char *audit_ptrace_mask(u32 mask)
  162. {
  163. switch (mask) {
  164. case MAY_READ:
  165. return "read";
  166. case MAY_WRITE:
  167. return "trace";
  168. case AA_MAY_BE_READ:
  169. return "readby";
  170. case AA_MAY_BE_TRACED:
  171. return "tracedby";
  172. }
  173. return "";
  174. }
  175. /* call back to audit ptrace fields */
  176. static void audit_ptrace_cb(struct audit_buffer *ab, void *va)
  177. {
  178. struct common_audit_data *sa = va;
  179. struct apparmor_audit_data *ad = aad(sa);
  180. if (ad->request & AA_PTRACE_PERM_MASK) {
  181. audit_log_format(ab, " requested_mask=\"%s\"",
  182. audit_ptrace_mask(ad->request));
  183. if (ad->denied & AA_PTRACE_PERM_MASK) {
  184. audit_log_format(ab, " denied_mask=\"%s\"",
  185. audit_ptrace_mask(ad->denied));
  186. }
  187. }
  188. audit_log_format(ab, " peer=");
  189. aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer,
  190. FLAGS_NONE, GFP_ATOMIC);
  191. }
  192. /* assumes check for RULE_MEDIATES is already done */
  193. /* TODO: conditionals */
  194. static int profile_ptrace_perm(const struct cred *cred,
  195. struct aa_profile *profile,
  196. struct aa_label *peer, u32 request,
  197. struct apparmor_audit_data *ad)
  198. {
  199. struct aa_ruleset *rules = profile->label.rules[0];
  200. struct aa_perms perms = { };
  201. ad->subj_cred = cred;
  202. ad->peer = peer;
  203. aa_profile_match_label(profile, rules, peer, AA_CLASS_PTRACE, request,
  204. &perms);
  205. aa_apply_modes_to_perms(profile, &perms);
  206. return aa_check_perms(profile, &perms, request, ad, audit_ptrace_cb);
  207. }
  208. static int profile_tracee_perm(const struct cred *cred,
  209. struct aa_profile *tracee,
  210. struct aa_label *tracer, u32 request,
  211. struct apparmor_audit_data *ad)
  212. {
  213. if (profile_unconfined(tracee) || unconfined(tracer) ||
  214. !label_mediates(&tracee->label, AA_CLASS_PTRACE))
  215. return 0;
  216. return profile_ptrace_perm(cred, tracee, tracer, request, ad);
  217. }
  218. static int profile_tracer_perm(const struct cred *cred,
  219. struct aa_profile *tracer,
  220. struct aa_label *tracee, u32 request,
  221. struct apparmor_audit_data *ad)
  222. {
  223. if (profile_unconfined(tracer))
  224. return 0;
  225. if (label_mediates(&tracer->label, AA_CLASS_PTRACE))
  226. return profile_ptrace_perm(cred, tracer, tracee, request, ad);
  227. /* profile uses the old style capability check for ptrace */
  228. if (&tracer->label == tracee)
  229. return 0;
  230. ad->subj_label = &tracer->label;
  231. ad->peer = tracee;
  232. ad->request = 0;
  233. ad->error = aa_capable(cred, &tracer->label, CAP_SYS_PTRACE,
  234. CAP_OPT_NONE);
  235. return aa_audit(AUDIT_APPARMOR_AUTO, tracer, ad, audit_ptrace_cb);
  236. }
  237. /**
  238. * aa_may_ptrace - test if tracer task can trace the tracee
  239. * @tracer_cred: cred of task doing the tracing (NOT NULL)
  240. * @tracer: label of the task doing the tracing (NOT NULL)
  241. * @tracee_cred: cred of task to be traced
  242. * @tracee: task label to be traced
  243. * @request: permission request
  244. *
  245. * Returns: %0 else error code if permission denied or error
  246. */
  247. int aa_may_ptrace(const struct cred *tracer_cred, struct aa_label *tracer,
  248. const struct cred *tracee_cred, struct aa_label *tracee,
  249. u32 request)
  250. {
  251. struct aa_profile *profile;
  252. u32 xrequest = request << PTRACE_PERM_SHIFT;
  253. DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, AA_CLASS_PTRACE, OP_PTRACE);
  254. return xcheck_labels(tracer, tracee, profile,
  255. profile_tracer_perm(tracer_cred, profile, tracee,
  256. request, &sa),
  257. profile_tracee_perm(tracee_cred, profile, tracer,
  258. xrequest, &sa));
  259. }
  260. static const char *get_current_exe_path(char *buffer, int buffer_size)
  261. {
  262. struct file *exe_file;
  263. struct path p;
  264. const char *path_str;
  265. exe_file = get_task_exe_file(current);
  266. if (!exe_file)
  267. return ERR_PTR(-ENOENT);
  268. p = exe_file->f_path;
  269. path_get(&p);
  270. if (aa_path_name(&p, FLAG_VIEW_SUBNS, buffer, &path_str, NULL, NULL))
  271. return ERR_PTR(-ENOMEM);
  272. fput(exe_file);
  273. path_put(&p);
  274. return path_str;
  275. }
  276. /* call back to audit ptrace fields */
  277. static void audit_ns_cb(struct audit_buffer *ab, void *va)
  278. {
  279. struct apparmor_audit_data *ad = aad_of_va(va);
  280. char *buffer;
  281. const char *path;
  282. if (ad->request & AA_USERNS_CREATE)
  283. audit_log_format(ab, " requested=\"userns_create\"");
  284. if (ad->denied & AA_USERNS_CREATE)
  285. audit_log_format(ab, " denied=\"userns_create\"");
  286. buffer = aa_get_buffer(false);
  287. if (!buffer)
  288. return; // OOM
  289. path = get_current_exe_path(buffer, aa_g_path_max);
  290. if (!IS_ERR(path))
  291. audit_log_format(ab, " execpath=\"%s\"", path);
  292. aa_put_buffer(buffer);
  293. }
  294. int aa_profile_ns_perm(struct aa_profile *profile,
  295. struct apparmor_audit_data *ad,
  296. u32 request)
  297. {
  298. struct aa_perms perms = { };
  299. int error = 0;
  300. ad->subj_label = &profile->label;
  301. ad->request = request;
  302. if (!profile_unconfined(profile)) {
  303. struct aa_ruleset *rules = profile->label.rules[0];
  304. aa_state_t state;
  305. state = RULE_MEDIATES(rules, ad->class);
  306. if (!state)
  307. /* TODO: add flag to complain about unmediated */
  308. return 0;
  309. perms = *aa_lookup_perms(rules->policy, state);
  310. aa_apply_modes_to_perms(profile, &perms);
  311. error = aa_check_perms(profile, &perms, request, ad,
  312. audit_ns_cb);
  313. }
  314. return error;
  315. }