Branch data Line data Source code
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 : : 15 : : #include "include/cred.h" 16 : : #include "include/task.h" 17 : : 18 : : /** 19 : : * aa_get_task_label - Get another task's label 20 : : * @task: task to query (NOT NULL) 21 : : * 22 : : * Returns: counted reference to @task's label 23 : : */ 24 : 0 : struct aa_label *aa_get_task_label(struct task_struct *task) 25 : : { 26 : : struct aa_label *p; 27 : : 28 : : rcu_read_lock(); 29 : 0 : p = aa_get_newest_label(__aa_task_raw_label(task)); 30 : : rcu_read_unlock(); 31 : : 32 : 0 : return p; 33 : : } 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 : 0 : 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 : : 47 : : AA_BUG(!label); 48 : : 49 [ # # ]: 0 : if (old == label) 50 : : return 0; 51 : : 52 [ # # ]: 0 : if (current_cred() != current_real_cred()) 53 : : return -EBUSY; 54 : : 55 : 0 : new = prepare_creds(); 56 [ # # ]: 0 : if (!new) 57 : : return -ENOMEM; 58 : : 59 [ # # # # ]: 0 : if (ctx->nnp && label_is_stale(ctx->nnp)) { 60 : : struct aa_label *tmp = ctx->nnp; 61 : : 62 : 0 : ctx->nnp = aa_get_newest_label(tmp); 63 : : aa_put_label(tmp); 64 : : } 65 [ # # # # ]: 0 : if (unconfined(label) || (labels_ns(old) != labels_ns(label))) 66 : : /* 67 : : * if switching to unconfined or a different label namespace 68 : : * clear out context state 69 : : */ 70 : 0 : aa_clear_task_ctx_trans(task_ctx(current)); 71 : : 72 : : /* 73 : : * 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 77 : : */ 78 : : aa_get_label(label); 79 : : aa_put_label(cred_label(new)); 80 : : set_cred_label(new, label); 81 : : 82 : 0 : commit_creds(new); 83 : 0 : return 0; 84 : : } 85 : : 86 : : 87 : : /** 88 : : * aa_set_current_onexec - set the tasks change_profile to happen onexec 89 : : * @label: system label to set at exec (MAYBE NULL to clear value) 90 : : * @stack: whether stacking should be done 91 : : * Returns: 0 or error on failure 92 : : */ 93 : 0 : int aa_set_current_onexec(struct aa_label *label, bool stack) 94 : : { 95 : 0 : struct aa_task_ctx *ctx = task_ctx(current); 96 : : 97 : : aa_get_label(label); 98 : 0 : aa_put_label(ctx->onexec); 99 : 0 : ctx->onexec = label; 100 : 0 : ctx->token = stack; 101 : : 102 : 0 : return 0; 103 : : } 104 : : 105 : : /** 106 : : * aa_set_current_hat - set the current tasks hat 107 : : * @label: label to set as the current hat (NOT NULL) 108 : : * @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 : : */ 115 : 0 : int aa_set_current_hat(struct aa_label *label, u64 token) 116 : : { 117 : 0 : struct aa_task_ctx *ctx = task_ctx(current); 118 : : struct cred *new; 119 : : 120 : 0 : new = prepare_creds(); 121 [ # # ]: 0 : if (!new) 122 : : return -ENOMEM; 123 : : AA_BUG(!label); 124 : : 125 [ # # ]: 0 : if (!ctx->previous) { 126 : : /* transfer refcount */ 127 : 0 : ctx->previous = cred_label(new); 128 : 0 : ctx->token = token; 129 [ # # ]: 0 : } else if (ctx->token == token) { 130 : : aa_put_label(cred_label(new)); 131 : : } else { 132 : : /* previous_profile && ctx->token != token */ 133 : 0 : abort_creds(new); 134 : 0 : return -EACCES; 135 : : } 136 : : 137 : 0 : set_cred_label(new, aa_get_newest_label(label)); 138 : : /* clear exec on switching context */ 139 : 0 : aa_put_label(ctx->onexec); 140 : 0 : ctx->onexec = NULL; 141 : : 142 : 0 : commit_creds(new); 143 : 0 : return 0; 144 : : } 145 : : 146 : : /** 147 : : * aa_restore_previous_label - exit from hat context restoring previous label 148 : : * @token: the token that must be matched to exit hat context 149 : : * 150 : : * Attempt to return out of a hat to the previous label. The token 151 : : * must match the stored token value. 152 : : * 153 : : * Returns: 0 or error of failure 154 : : */ 155 : 0 : int aa_restore_previous_label(u64 token) 156 : : { 157 : 0 : struct aa_task_ctx *ctx = task_ctx(current); 158 : : struct cred *new; 159 : : 160 [ # # ]: 0 : if (ctx->token != token) 161 : : return -EACCES; 162 : : /* ignore restores when there is no saved label */ 163 [ # # ]: 0 : if (!ctx->previous) 164 : : return 0; 165 : : 166 : 0 : new = prepare_creds(); 167 [ # # ]: 0 : if (!new) 168 : : return -ENOMEM; 169 : : 170 : : aa_put_label(cred_label(new)); 171 : 0 : set_cred_label(new, aa_get_newest_label(ctx->previous)); 172 : : AA_BUG(!cred_label(new)); 173 : : /* clear exec && prev information when restoring to previous context */ 174 : 0 : aa_clear_task_ctx_trans(ctx); 175 : : 176 : 0 : commit_creds(new); 177 : : 178 : 0 : return 0; 179 : : }