^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * AppArmor security module
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This file contains AppArmor task related definitions and mediation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright 2017 Canonical Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * TODO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * If a task uses change_hat it currently does not return to the old
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * cred or task context but instead creates a new one. Ideally the task
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * should return to the previous cred if it has not been modified.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include "include/cred.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include "include/task.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * aa_get_task_label - Get another task's label
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * @task: task to query (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * Returns: counted reference to @task's label
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) struct aa_label *aa_get_task_label(struct task_struct *task)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct aa_label *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) rcu_read_lock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) p = aa_get_newest_label(__aa_task_raw_label(task));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) rcu_read_unlock();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) return p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * aa_replace_current_label - replace the current tasks label
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * @label: new label (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * Returns: 0 or error on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) int aa_replace_current_label(struct aa_label *label)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) struct aa_label *old = aa_current_raw_label();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) struct aa_task_ctx *ctx = task_ctx(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct cred *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) AA_BUG(!label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (old == label)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (current_cred() != current_real_cred())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) new = prepare_creds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (ctx->nnp && label_is_stale(ctx->nnp)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct aa_label *tmp = ctx->nnp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) ctx->nnp = aa_get_newest_label(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) aa_put_label(tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (unconfined(label) || (labels_ns(old) != labels_ns(label)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) * if switching to unconfined or a different label namespace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * clear out context state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) aa_clear_task_ctx_trans(task_ctx(current));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * be careful switching cred label, when racing replacement it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * is possible that the cred labels's->proxy->label is the reference
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * keeping @label valid, so make sure to get its reference before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * dropping the reference on the cred's label
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) aa_get_label(label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) aa_put_label(cred_label(new));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) set_cred_label(new, label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) commit_creds(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * aa_set_current_onexec - set the tasks change_profile to happen onexec
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * @label: system label to set at exec (MAYBE NULL to clear value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * @stack: whether stacking should be done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * Returns: 0 or error on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) int aa_set_current_onexec(struct aa_label *label, bool stack)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) struct aa_task_ctx *ctx = task_ctx(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) aa_get_label(label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) aa_put_label(ctx->onexec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) ctx->onexec = label;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) ctx->token = stack;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * aa_set_current_hat - set the current tasks hat
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * @label: label to set as the current hat (NOT NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * @token: token value that must be specified to change from the hat
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * Do switch of tasks hat. If the task is currently in a hat
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * validate the token to match.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * Returns: 0 or error on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) int aa_set_current_hat(struct aa_label *label, u64 token)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct aa_task_ctx *ctx = task_ctx(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) struct cred *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) new = prepare_creds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) AA_BUG(!label);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (!ctx->previous) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* transfer refcount */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) ctx->previous = cred_label(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) ctx->token = token;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) } else if (ctx->token == token) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) aa_put_label(cred_label(new));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) /* previous_profile && ctx->token != token */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) abort_creds(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) set_cred_label(new, aa_get_newest_label(label));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* clear exec on switching context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) aa_put_label(ctx->onexec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) ctx->onexec = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) commit_creds(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) * aa_restore_previous_label - exit from hat context restoring previous label
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) * @token: the token that must be matched to exit hat context
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) * Attempt to return out of a hat to the previous label. The token
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) * must match the stored token value.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) * Returns: 0 or error of failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) int aa_restore_previous_label(u64 token)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) struct aa_task_ctx *ctx = task_ctx(current);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) struct cred *new;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (ctx->token != token)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) return -EACCES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /* ignore restores when there is no saved label */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) if (!ctx->previous)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) new = prepare_creds();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) if (!new)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) aa_put_label(cred_label(new));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) set_cred_label(new, aa_get_newest_label(ctx->previous));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) AA_BUG(!cred_label(new));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) /* clear exec && prev information when restoring to previous context */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) aa_clear_task_ctx_trans(ctx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) commit_creds(new);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }