1 /* 2 * AppArmor security module 3 * 4 * This file contains AppArmor contexts used to associate "labels" to objects. 5 * 6 * Copyright (C) 1998-2008 Novell/SUSE 7 * Copyright 2009-2010 Canonical Ltd. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation, version 2 of the 12 * License. 13 */ 14 15 #ifndef __AA_CONTEXT_H 16 #define __AA_CONTEXT_H 17 18 #include <linux/cred.h> 19 #include <linux/slab.h> 20 #include <linux/sched.h> 21 22 #include "label.h" 23 #include "policy_ns.h" 24 25 #define cred_ctx(X) ((X)->security) 26 #define current_ctx() cred_ctx(current_cred()) 27 28 /** 29 * struct aa_task_ctx - primary label for confined tasks 30 * @label: the current label (NOT NULL) 31 * @exec: label to transition to on next exec (MAYBE NULL) 32 * @previous: label the task may return to (MAYBE NULL) 33 * @token: magic value the task must know for returning to @previous 34 * 35 * Contains the task's current label (which could change due to 36 * change_hat). Plus the hat_magic needed during change_hat. 37 * 38 * TODO: make so a task can be confined by a stack of contexts 39 */ 40 struct aa_task_ctx { 41 struct aa_label *label; 42 struct aa_label *onexec; 43 struct aa_label *previous; 44 u64 token; 45 }; 46 47 struct aa_task_ctx *aa_alloc_task_context(gfp_t flags); 48 void aa_free_task_context(struct aa_task_ctx *ctx); 49 void aa_dup_task_context(struct aa_task_ctx *new, 50 const struct aa_task_ctx *old); 51 int aa_replace_current_label(struct aa_label *label); 52 int aa_set_current_onexec(struct aa_label *label, bool stack); 53 int aa_set_current_hat(struct aa_label *label, u64 token); 54 int aa_restore_previous_label(u64 cookie); 55 struct aa_label *aa_get_task_label(struct task_struct *task); 56 57 58 /** 59 * aa_cred_raw_label - obtain cred's label 60 * @cred: cred to obtain label from (NOT NULL) 61 * 62 * Returns: confining label 63 * 64 * does NOT increment reference count 65 */ aa_cred_raw_label(const struct cred * cred)66static inline struct aa_label *aa_cred_raw_label(const struct cred *cred) 67 { 68 struct aa_task_ctx *ctx = cred_ctx(cred); 69 70 AA_BUG(!ctx || !ctx->label); 71 return ctx->label; 72 } 73 74 /** 75 * aa_get_newest_cred_label - obtain the newest label on a cred 76 * @cred: cred to obtain label from (NOT NULL) 77 * 78 * Returns: newest version of confining label 79 */ aa_get_newest_cred_label(const struct cred * cred)80static inline struct aa_label *aa_get_newest_cred_label(const struct cred *cred) 81 { 82 return aa_get_newest_label(aa_cred_raw_label(cred)); 83 } 84 85 /** 86 * __aa_task_raw_label - retrieve another task's label 87 * @task: task to query (NOT NULL) 88 * 89 * Returns: @task's label without incrementing its ref count 90 * 91 * If @task != current needs to be called in RCU safe critical section 92 */ __aa_task_raw_label(struct task_struct * task)93static inline struct aa_label *__aa_task_raw_label(struct task_struct *task) 94 { 95 return aa_cred_raw_label(__task_cred(task)); 96 } 97 98 /** 99 * __aa_task_is_confined - determine if @task has any confinement 100 * @task: task to check confinement of (NOT NULL) 101 * 102 * If @task != current needs to be called in RCU safe critical section 103 */ __aa_task_is_confined(struct task_struct * task)104static inline bool __aa_task_is_confined(struct task_struct *task) 105 { 106 return !unconfined(__aa_task_raw_label(task)); 107 } 108 109 /** 110 * aa_current_raw_label - find the current tasks confining label 111 * 112 * Returns: up to date confining label or the ns unconfined label (NOT NULL) 113 * 114 * This fn will not update the tasks cred to the most up to date version 115 * of the label so it is safe to call when inside of locks. 116 */ aa_current_raw_label(void)117static inline struct aa_label *aa_current_raw_label(void) 118 { 119 return aa_cred_raw_label(current_cred()); 120 } 121 122 /** 123 * aa_get_current_label - get the newest version of the current tasks label 124 * 125 * Returns: newest version of confining label (NOT NULL) 126 * 127 * This fn will not update the tasks cred, so it is safe inside of locks 128 * 129 * The returned reference must be put with aa_put_label() 130 */ aa_get_current_label(void)131static inline struct aa_label *aa_get_current_label(void) 132 { 133 struct aa_label *l = aa_current_raw_label(); 134 135 if (label_is_stale(l)) 136 return aa_get_newest_label(l); 137 return aa_get_label(l); 138 } 139 140 #define __end_current_label_crit_section(X) end_current_label_crit_section(X) 141 142 /** 143 * end_label_crit_section - put a reference found with begin_current_label.. 144 * @label: label reference to put 145 * 146 * Should only be used with a reference obtained with 147 * begin_current_label_crit_section and never used in situations where the 148 * task cred may be updated 149 */ end_current_label_crit_section(struct aa_label * label)150static inline void end_current_label_crit_section(struct aa_label *label) 151 { 152 if (label != aa_current_raw_label()) 153 aa_put_label(label); 154 } 155 156 /** 157 * __begin_current_label_crit_section - current's confining label 158 * 159 * Returns: up to date confining label or the ns unconfined label (NOT NULL) 160 * 161 * safe to call inside locks 162 * 163 * The returned reference must be put with __end_current_label_crit_section() 164 * This must NOT be used if the task cred could be updated within the 165 * critical section between __begin_current_label_crit_section() .. 166 * __end_current_label_crit_section() 167 */ __begin_current_label_crit_section(void)168static inline struct aa_label *__begin_current_label_crit_section(void) 169 { 170 struct aa_label *label = aa_current_raw_label(); 171 172 if (label_is_stale(label)) 173 label = aa_get_newest_label(label); 174 175 return label; 176 } 177 178 /** 179 * begin_current_label_crit_section - current's confining label and update it 180 * 181 * Returns: up to date confining label or the ns unconfined label (NOT NULL) 182 * 183 * Not safe to call inside locks 184 * 185 * The returned reference must be put with end_current_label_crit_section() 186 * This must NOT be used if the task cred could be updated within the 187 * critical section between begin_current_label_crit_section() .. 188 * end_current_label_crit_section() 189 */ begin_current_label_crit_section(void)190static inline struct aa_label *begin_current_label_crit_section(void) 191 { 192 struct aa_label *label = aa_current_raw_label(); 193 194 might_sleep(); 195 196 if (label_is_stale(label)) { 197 label = aa_get_newest_label(label); 198 if (aa_replace_current_label(label) == 0) 199 /* task cred will keep the reference */ 200 aa_put_label(label); 201 } 202 203 return label; 204 } 205 aa_get_current_ns(void)206static inline struct aa_ns *aa_get_current_ns(void) 207 { 208 struct aa_label *label; 209 struct aa_ns *ns; 210 211 label = __begin_current_label_crit_section(); 212 ns = aa_get_ns(labels_ns(label)); 213 __end_current_label_crit_section(label); 214 215 return ns; 216 } 217 218 /** 219 * aa_clear_task_ctx_trans - clear transition tracking info from the ctx 220 * @ctx: task context to clear (NOT NULL) 221 */ aa_clear_task_ctx_trans(struct aa_task_ctx * ctx)222static inline void aa_clear_task_ctx_trans(struct aa_task_ctx *ctx) 223 { 224 aa_put_label(ctx->previous); 225 aa_put_label(ctx->onexec); 226 ctx->previous = NULL; 227 ctx->onexec = NULL; 228 ctx->token = 0; 229 } 230 231 #endif /* __AA_CONTEXT_H */ 232