at v4.13 5.6 kB view raw
1/* 2 * AppArmor security module 3 * 4 * This file contains AppArmor functions used to manipulate object security 5 * contexts. 6 * 7 * Copyright (C) 1998-2008 Novell/SUSE 8 * Copyright 2009-2010 Canonical Ltd. 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License as 12 * published by the Free Software Foundation, version 2 of the 13 * License. 14 * 15 * 16 * AppArmor sets confinement on every task, via the the aa_task_ctx and 17 * the aa_task_ctx.label, both of which are required and are not allowed 18 * to be NULL. The aa_task_ctx is not reference counted and is unique 19 * to each cred (which is reference count). The label pointed to by 20 * the task_ctx is reference counted. 21 * 22 * TODO 23 * If a task uses change_hat it currently does not return to the old 24 * cred or task context but instead creates a new one. Ideally the task 25 * should return to the previous cred if it has not been modified. 26 * 27 */ 28 29#include "include/context.h" 30#include "include/policy.h" 31 32/** 33 * aa_alloc_task_context - allocate a new task_ctx 34 * @flags: gfp flags for allocation 35 * 36 * Returns: allocated buffer or NULL on failure 37 */ 38struct aa_task_ctx *aa_alloc_task_context(gfp_t flags) 39{ 40 return kzalloc(sizeof(struct aa_task_ctx), flags); 41} 42 43/** 44 * aa_free_task_context - free a task_ctx 45 * @ctx: task_ctx to free (MAYBE NULL) 46 */ 47void aa_free_task_context(struct aa_task_ctx *ctx) 48{ 49 if (ctx) { 50 aa_put_label(ctx->label); 51 aa_put_label(ctx->previous); 52 aa_put_label(ctx->onexec); 53 54 kzfree(ctx); 55 } 56} 57 58/** 59 * aa_dup_task_context - duplicate a task context, incrementing reference counts 60 * @new: a blank task context (NOT NULL) 61 * @old: the task context to copy (NOT NULL) 62 */ 63void aa_dup_task_context(struct aa_task_ctx *new, const struct aa_task_ctx *old) 64{ 65 *new = *old; 66 aa_get_label(new->label); 67 aa_get_label(new->previous); 68 aa_get_label(new->onexec); 69} 70 71/** 72 * aa_get_task_label - Get another task's label 73 * @task: task to query (NOT NULL) 74 * 75 * Returns: counted reference to @task's label 76 */ 77struct aa_label *aa_get_task_label(struct task_struct *task) 78{ 79 struct aa_label *p; 80 81 rcu_read_lock(); 82 p = aa_get_newest_label(__aa_task_raw_label(task)); 83 rcu_read_unlock(); 84 85 return p; 86} 87 88/** 89 * aa_replace_current_label - replace the current tasks label 90 * @label: new label (NOT NULL) 91 * 92 * Returns: 0 or error on failure 93 */ 94int aa_replace_current_label(struct aa_label *label) 95{ 96 struct aa_task_ctx *ctx = current_ctx(); 97 struct cred *new; 98 AA_BUG(!label); 99 100 if (ctx->label == label) 101 return 0; 102 103 if (current_cred() != current_real_cred()) 104 return -EBUSY; 105 106 new = prepare_creds(); 107 if (!new) 108 return -ENOMEM; 109 110 ctx = cred_ctx(new); 111 if (unconfined(label) || (labels_ns(ctx->label) != labels_ns(label))) 112 /* if switching to unconfined or a different label namespace 113 * clear out context state 114 */ 115 aa_clear_task_ctx_trans(ctx); 116 117 /* 118 * be careful switching ctx->profile, when racing replacement it 119 * is possible that ctx->profile->proxy->profile is the reference 120 * keeping @profile valid, so make sure to get its reference before 121 * dropping the reference on ctx->profile 122 */ 123 aa_get_label(label); 124 aa_put_label(ctx->label); 125 ctx->label = label; 126 127 commit_creds(new); 128 return 0; 129} 130 131/** 132 * aa_set_current_onexec - set the tasks change_profile to happen onexec 133 * @label: system label to set at exec (MAYBE NULL to clear value) 134 * @stack: whether stacking should be done 135 * Returns: 0 or error on failure 136 */ 137int aa_set_current_onexec(struct aa_label *label, bool stack) 138{ 139 struct aa_task_ctx *ctx; 140 struct cred *new = prepare_creds(); 141 if (!new) 142 return -ENOMEM; 143 144 ctx = cred_ctx(new); 145 aa_get_label(label); 146 aa_clear_task_ctx_trans(ctx); 147 ctx->onexec = label; 148 ctx->token = stack; 149 150 commit_creds(new); 151 return 0; 152} 153 154/** 155 * aa_set_current_hat - set the current tasks hat 156 * @label: label to set as the current hat (NOT NULL) 157 * @token: token value that must be specified to change from the hat 158 * 159 * Do switch of tasks hat. If the task is currently in a hat 160 * validate the token to match. 161 * 162 * Returns: 0 or error on failure 163 */ 164int aa_set_current_hat(struct aa_label *label, u64 token) 165{ 166 struct aa_task_ctx *ctx; 167 struct cred *new = prepare_creds(); 168 if (!new) 169 return -ENOMEM; 170 AA_BUG(!label); 171 172 ctx = cred_ctx(new); 173 if (!ctx->previous) { 174 /* transfer refcount */ 175 ctx->previous = ctx->label; 176 ctx->token = token; 177 } else if (ctx->token == token) { 178 aa_put_label(ctx->label); 179 } else { 180 /* previous_profile && ctx->token != token */ 181 abort_creds(new); 182 return -EACCES; 183 } 184 ctx->label = aa_get_newest_label(label); 185 /* clear exec on switching context */ 186 aa_put_label(ctx->onexec); 187 ctx->onexec = NULL; 188 189 commit_creds(new); 190 return 0; 191} 192 193/** 194 * aa_restore_previous_label - exit from hat context restoring previous label 195 * @token: the token that must be matched to exit hat context 196 * 197 * Attempt to return out of a hat to the previous label. The token 198 * must match the stored token value. 199 * 200 * Returns: 0 or error of failure 201 */ 202int aa_restore_previous_label(u64 token) 203{ 204 struct aa_task_ctx *ctx; 205 struct cred *new = prepare_creds(); 206 if (!new) 207 return -ENOMEM; 208 209 ctx = cred_ctx(new); 210 if (ctx->token != token) { 211 abort_creds(new); 212 return -EACCES; 213 } 214 /* ignore restores when there is no saved label */ 215 if (!ctx->previous) { 216 abort_creds(new); 217 return 0; 218 } 219 220 aa_put_label(ctx->label); 221 ctx->label = aa_get_newest_label(ctx->previous); 222 AA_BUG(!ctx->label); 223 /* clear exec && prev information when restoring to previous context */ 224 aa_clear_task_ctx_trans(ctx); 225 226 commit_creds(new); 227 return 0; 228}