blob: d17130ee6795df3f907f494ff5e5d495e8389f44 [file] [log] [blame]
Thomas Gleixnerb886d83c2019-06-01 10:08:55 +02001// SPDX-License-Identifier: GPL-2.0-only
John Johansenc75afcd2010-07-29 14:47:59 -07002/*
3 * AppArmor security module
4 *
John Johansende62de52017-10-08 00:43:02 -07005 * This file contains AppArmor task related definitions and mediation
John Johansenc75afcd2010-07-29 14:47:59 -07006 *
John Johansende62de52017-10-08 00:43:02 -07007 * Copyright 2017 Canonical Ltd.
John Johansenc75afcd2010-07-29 14:47:59 -07008 *
John Johansenc75afcd2010-07-29 14:47:59 -07009 * 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.
John Johansenc75afcd2010-07-29 14:47:59 -070013 */
14
John Johansend8889d42017-10-11 01:04:48 -070015#include "include/cred.h"
John Johansende62de52017-10-08 00:43:02 -070016#include "include/task.h"
John Johansenc75afcd2010-07-29 14:47:59 -070017
18/**
John Johansen637f6882017-06-09 08:14:28 -070019 * aa_get_task_label - Get another task's label
John Johansen3cfcc192013-02-18 16:03:34 -080020 * @task: task to query (NOT NULL)
21 *
John Johansen637f6882017-06-09 08:14:28 -070022 * Returns: counted reference to @task's label
John Johansen3cfcc192013-02-18 16:03:34 -080023 */
John Johansen637f6882017-06-09 08:14:28 -070024struct aa_label *aa_get_task_label(struct task_struct *task)
John Johansen3cfcc192013-02-18 16:03:34 -080025{
John Johansen637f6882017-06-09 08:14:28 -070026 struct aa_label *p;
John Johansen3cfcc192013-02-18 16:03:34 -080027
28 rcu_read_lock();
John Johansen637f6882017-06-09 08:14:28 -070029 p = aa_get_newest_label(__aa_task_raw_label(task));
John Johansen3cfcc192013-02-18 16:03:34 -080030 rcu_read_unlock();
31
32 return p;
33}
34
35/**
John Johansen637f6882017-06-09 08:14:28 -070036 * aa_replace_current_label - replace the current tasks label
37 * @label: new label (NOT NULL)
John Johansenc75afcd2010-07-29 14:47:59 -070038 *
39 * Returns: 0 or error on failure
40 */
John Johansen637f6882017-06-09 08:14:28 -070041int aa_replace_current_label(struct aa_label *label)
John Johansenc75afcd2010-07-29 14:47:59 -070042{
John Johansend9087c42017-01-27 03:53:53 -080043 struct aa_label *old = aa_current_raw_label();
John Johansen9fcf78c2017-10-08 18:26:19 -070044 struct aa_task_ctx *ctx = task_ctx(current);
John Johansenc75afcd2010-07-29 14:47:59 -070045 struct cred *new;
John Johansend9087c42017-01-27 03:53:53 -080046
John Johansen637f6882017-06-09 08:14:28 -070047 AA_BUG(!label);
John Johansenc75afcd2010-07-29 14:47:59 -070048
John Johansend9087c42017-01-27 03:53:53 -080049 if (old == label)
John Johansenc75afcd2010-07-29 14:47:59 -070050 return 0;
51
John Johansena20aa952017-01-16 00:42:59 -080052 if (current_cred() != current_real_cred())
53 return -EBUSY;
54
John Johansenc75afcd2010-07-29 14:47:59 -070055 new = prepare_creds();
56 if (!new)
57 return -ENOMEM;
58
John Johansen9fcf78c2017-10-08 18:26:19 -070059 if (ctx->nnp && label_is_stale(ctx->nnp)) {
60 struct aa_label *tmp = ctx->nnp;
61
62 ctx->nnp = aa_get_newest_label(tmp);
63 aa_put_label(tmp);
64 }
John Johansend9087c42017-01-27 03:53:53 -080065 if (unconfined(label) || (labels_ns(old) != labels_ns(label)))
66 /*
67 * if switching to unconfined or a different label namespace
John Johansenc75afcd2010-07-29 14:47:59 -070068 * clear out context state
69 */
John Johansende62de52017-10-08 00:43:02 -070070 aa_clear_task_ctx_trans(task_ctx(current));
John Johansen7a2871b2013-02-18 16:05:34 -080071
John Johansen55a26eb2017-01-16 00:43:00 -080072 /*
John Johansend9087c42017-01-27 03:53:53 -080073 * be careful switching cred label, when racing replacement it
74 * is possible that the cred labels's->proxy->label is the reference
75 * keeping @label valid, so make sure to get its reference before
76 * dropping the reference on the cred's label
John Johansen55a26eb2017-01-16 00:43:00 -080077 */
John Johansen637f6882017-06-09 08:14:28 -070078 aa_get_label(label);
John Johansend9087c42017-01-27 03:53:53 -080079 aa_put_label(cred_label(new));
Casey Schaufler69b5a442018-09-21 17:17:59 -070080 set_cred_label(new, label);
John Johansenc75afcd2010-07-29 14:47:59 -070081
82 commit_creds(new);
83 return 0;
84}
85
John Johansende62de52017-10-08 00:43:02 -070086
John Johansenc75afcd2010-07-29 14:47:59 -070087/**
88 * aa_set_current_onexec - set the tasks change_profile to happen onexec
John Johansen637f6882017-06-09 08:14:28 -070089 * @label: system label to set at exec (MAYBE NULL to clear value)
90 * @stack: whether stacking should be done
John Johansenc75afcd2010-07-29 14:47:59 -070091 * Returns: 0 or error on failure
92 */
John Johansen637f6882017-06-09 08:14:28 -070093int aa_set_current_onexec(struct aa_label *label, bool stack)
John Johansenc75afcd2010-07-29 14:47:59 -070094{
John Johansende62de52017-10-08 00:43:02 -070095 struct aa_task_ctx *ctx = task_ctx(current);
John Johansenc75afcd2010-07-29 14:47:59 -070096
John Johansen637f6882017-06-09 08:14:28 -070097 aa_get_label(label);
John Johansen3b529a72017-01-20 01:59:25 -080098 aa_put_label(ctx->onexec);
John Johansen637f6882017-06-09 08:14:28 -070099 ctx->onexec = label;
100 ctx->token = stack;
John Johansenc75afcd2010-07-29 14:47:59 -0700101
John Johansenc75afcd2010-07-29 14:47:59 -0700102 return 0;
103}
104
105/**
106 * aa_set_current_hat - set the current tasks hat
John Johansen637f6882017-06-09 08:14:28 -0700107 * @label: label to set as the current hat (NOT NULL)
John Johansenc75afcd2010-07-29 14:47:59 -0700108 * @token: token value that must be specified to change from the hat
109 *
110 * Do switch of tasks hat. If the task is currently in a hat
111 * validate the token to match.
112 *
113 * Returns: 0 or error on failure
114 */
John Johansen637f6882017-06-09 08:14:28 -0700115int aa_set_current_hat(struct aa_label *label, u64 token)
John Johansenc75afcd2010-07-29 14:47:59 -0700116{
John Johansende62de52017-10-08 00:43:02 -0700117 struct aa_task_ctx *ctx = task_ctx(current);
John Johansend9087c42017-01-27 03:53:53 -0800118 struct cred *new;
John Johansen3b529a72017-01-20 01:59:25 -0800119
John Johansend9087c42017-01-27 03:53:53 -0800120 new = prepare_creds();
John Johansenc75afcd2010-07-29 14:47:59 -0700121 if (!new)
122 return -ENOMEM;
John Johansen637f6882017-06-09 08:14:28 -0700123 AA_BUG(!label);
John Johansenc75afcd2010-07-29 14:47:59 -0700124
John Johansenf1752212017-01-27 04:09:40 -0800125 if (!ctx->previous) {
John Johansenc75afcd2010-07-29 14:47:59 -0700126 /* transfer refcount */
John Johansenf1752212017-01-27 04:09:40 -0800127 ctx->previous = cred_label(new);
128 ctx->token = token;
129 } else if (ctx->token == token) {
John Johansend9087c42017-01-27 03:53:53 -0800130 aa_put_label(cred_label(new));
John Johansenc75afcd2010-07-29 14:47:59 -0700131 } else {
John Johansen55a26eb2017-01-16 00:43:00 -0800132 /* previous_profile && ctx->token != token */
John Johansenc75afcd2010-07-29 14:47:59 -0700133 abort_creds(new);
134 return -EACCES;
135 }
John Johansen3b529a72017-01-20 01:59:25 -0800136
Casey Schaufler69b5a442018-09-21 17:17:59 -0700137 set_cred_label(new, aa_get_newest_label(label));
John Johansenc75afcd2010-07-29 14:47:59 -0700138 /* clear exec on switching context */
John Johansenf1752212017-01-27 04:09:40 -0800139 aa_put_label(ctx->onexec);
140 ctx->onexec = NULL;
John Johansenc75afcd2010-07-29 14:47:59 -0700141
142 commit_creds(new);
143 return 0;
144}
145
146/**
John Johansen637f6882017-06-09 08:14:28 -0700147 * aa_restore_previous_label - exit from hat context restoring previous label
John Johansenc75afcd2010-07-29 14:47:59 -0700148 * @token: the token that must be matched to exit hat context
149 *
John Johansen637f6882017-06-09 08:14:28 -0700150 * Attempt to return out of a hat to the previous label. The token
John Johansenc75afcd2010-07-29 14:47:59 -0700151 * must match the stored token value.
152 *
153 * Returns: 0 or error of failure
154 */
John Johansen637f6882017-06-09 08:14:28 -0700155int aa_restore_previous_label(u64 token)
John Johansenc75afcd2010-07-29 14:47:59 -0700156{
John Johansende62de52017-10-08 00:43:02 -0700157 struct aa_task_ctx *ctx = task_ctx(current);
John Johansen3b529a72017-01-20 01:59:25 -0800158 struct cred *new;
159
John Johansenf1752212017-01-27 04:09:40 -0800160 if (ctx->token != token)
John Johansen3b529a72017-01-20 01:59:25 -0800161 return -EACCES;
162 /* ignore restores when there is no saved label */
John Johansenf1752212017-01-27 04:09:40 -0800163 if (!ctx->previous)
John Johansen3b529a72017-01-20 01:59:25 -0800164 return 0;
165
166 new = prepare_creds();
John Johansenc75afcd2010-07-29 14:47:59 -0700167 if (!new)
168 return -ENOMEM;
John Johansenc75afcd2010-07-29 14:47:59 -0700169
John Johansend9087c42017-01-27 03:53:53 -0800170 aa_put_label(cred_label(new));
Casey Schaufler69b5a442018-09-21 17:17:59 -0700171 set_cred_label(new, aa_get_newest_label(ctx->previous));
John Johansend9087c42017-01-27 03:53:53 -0800172 AA_BUG(!cred_label(new));
John Johansen7a2871b2013-02-18 16:05:34 -0800173 /* clear exec && prev information when restoring to previous context */
John Johansenf1752212017-01-27 04:09:40 -0800174 aa_clear_task_ctx_trans(ctx);
John Johansenc75afcd2010-07-29 14:47:59 -0700175
176 commit_creds(new);
John Johansen3b529a72017-01-20 01:59:25 -0800177
John Johansenc75afcd2010-07-29 14:47:59 -0700178 return 0;
179}