task.c 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * AppArmor security module
  3. *
  4. * This file contains AppArmor task related definitions and mediation
  5. *
  6. * Copyright 2017 Canonical Ltd.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License as
  10. * published by the Free Software Foundation, version 2 of the
  11. * License.
  12. *
  13. * TODO
  14. * If a task uses change_hat it currently does not return to the old
  15. * cred or task context but instead creates a new one. Ideally the task
  16. * should return to the previous cred if it has not been modified.
  17. */
  18. #include "include/cred.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. 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. 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. 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. }