task.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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 cred *new;
  44. AA_BUG(!label);
  45. if (old == label)
  46. return 0;
  47. if (current_cred() != current_real_cred())
  48. return -EBUSY;
  49. new = prepare_creds();
  50. if (!new)
  51. return -ENOMEM;
  52. if (unconfined(label) || (labels_ns(old) != labels_ns(label)))
  53. /*
  54. * if switching to unconfined or a different label namespace
  55. * clear out context state
  56. */
  57. aa_clear_task_ctx_trans(task_ctx(current));
  58. /*
  59. * be careful switching cred label, when racing replacement it
  60. * is possible that the cred labels's->proxy->label is the reference
  61. * keeping @label valid, so make sure to get its reference before
  62. * dropping the reference on the cred's label
  63. */
  64. aa_get_label(label);
  65. aa_put_label(cred_label(new));
  66. cred_label(new) = label;
  67. commit_creds(new);
  68. return 0;
  69. }
  70. /**
  71. * aa_set_current_onexec - set the tasks change_profile to happen onexec
  72. * @label: system label to set at exec (MAYBE NULL to clear value)
  73. * @stack: whether stacking should be done
  74. * Returns: 0 or error on failure
  75. */
  76. int aa_set_current_onexec(struct aa_label *label, bool stack)
  77. {
  78. struct aa_task_ctx *ctx = task_ctx(current);
  79. aa_get_label(label);
  80. aa_put_label(ctx->onexec);
  81. ctx->onexec = label;
  82. ctx->token = stack;
  83. return 0;
  84. }
  85. /**
  86. * aa_set_current_hat - set the current tasks hat
  87. * @label: label to set as the current hat (NOT NULL)
  88. * @token: token value that must be specified to change from the hat
  89. *
  90. * Do switch of tasks hat. If the task is currently in a hat
  91. * validate the token to match.
  92. *
  93. * Returns: 0 or error on failure
  94. */
  95. int aa_set_current_hat(struct aa_label *label, u64 token)
  96. {
  97. struct aa_task_ctx *ctx = task_ctx(current);
  98. struct cred *new;
  99. new = prepare_creds();
  100. if (!new)
  101. return -ENOMEM;
  102. AA_BUG(!label);
  103. if (!ctx->previous) {
  104. /* transfer refcount */
  105. ctx->previous = cred_label(new);
  106. ctx->token = token;
  107. } else if (ctx->token == token) {
  108. aa_put_label(cred_label(new));
  109. } else {
  110. /* previous_profile && ctx->token != token */
  111. abort_creds(new);
  112. return -EACCES;
  113. }
  114. cred_label(new) = aa_get_newest_label(label);
  115. /* clear exec on switching context */
  116. aa_put_label(ctx->onexec);
  117. ctx->onexec = NULL;
  118. commit_creds(new);
  119. return 0;
  120. }
  121. /**
  122. * aa_restore_previous_label - exit from hat context restoring previous label
  123. * @token: the token that must be matched to exit hat context
  124. *
  125. * Attempt to return out of a hat to the previous label. The token
  126. * must match the stored token value.
  127. *
  128. * Returns: 0 or error of failure
  129. */
  130. int aa_restore_previous_label(u64 token)
  131. {
  132. struct aa_task_ctx *ctx = task_ctx(current);
  133. struct cred *new;
  134. if (ctx->token != token)
  135. return -EACCES;
  136. /* ignore restores when there is no saved label */
  137. if (!ctx->previous)
  138. return 0;
  139. new = prepare_creds();
  140. if (!new)
  141. return -ENOMEM;
  142. aa_put_label(cred_label(new));
  143. cred_label(new) = aa_get_newest_label(ctx->previous);
  144. AA_BUG(!cred_label(new));
  145. /* clear exec && prev information when restoring to previous context */
  146. aa_clear_task_ctx_trans(ctx);
  147. commit_creds(new);
  148. return 0;
  149. }