Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

apparmor: add the base fns() for domain labels

Begin moving apparmor to using broader domain labels, that will allow
run time computation of domain type splitting via "stacking" of
profiles into a domain label vec.

Signed-off-by: John Johansen <john.johansen@canonical.com>

+2561
+441
security/apparmor/include/label.h
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor label definitions 5 + * 6 + * Copyright 2017 Canonical Ltd. 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License as 10 + * published by the Free Software Foundation, version 2 of the 11 + * License. 12 + */ 13 + 14 + #ifndef __AA_LABEL_H 15 + #define __AA_LABEL_H 16 + 17 + #include <linux/atomic.h> 18 + #include <linux/audit.h> 19 + #include <linux/rbtree.h> 20 + #include <linux/rcupdate.h> 21 + 22 + #include "apparmor.h" 23 + #include "lib.h" 24 + 25 + struct aa_ns; 26 + 27 + #define LOCAL_VEC_ENTRIES 8 28 + #define DEFINE_VEC(T, V) \ 29 + struct aa_ ## T *(_ ## V ## _localtmp)[LOCAL_VEC_ENTRIES]; \ 30 + struct aa_ ## T **(V) 31 + 32 + #define vec_setup(T, V, N, GFP) \ 33 + ({ \ 34 + if ((N) <= LOCAL_VEC_ENTRIES) { \ 35 + typeof(N) i; \ 36 + (V) = (_ ## V ## _localtmp); \ 37 + for (i = 0; i < (N); i++) \ 38 + (V)[i] = NULL; \ 39 + } else \ 40 + (V) = kzalloc(sizeof(struct aa_ ## T *) * (N), (GFP)); \ 41 + (V) ? 0 : -ENOMEM; \ 42 + }) 43 + 44 + #define vec_cleanup(T, V, N) \ 45 + do { \ 46 + int i; \ 47 + for (i = 0; i < (N); i++) { \ 48 + if (!IS_ERR_OR_NULL((V)[i])) \ 49 + aa_put_ ## T((V)[i]); \ 50 + } \ 51 + if ((V) != _ ## V ## _localtmp) \ 52 + kfree(V); \ 53 + } while (0) 54 + 55 + #define vec_last(VEC, SIZE) ((VEC)[(SIZE) - 1]) 56 + #define vec_ns(VEC, SIZE) (vec_last((VEC), (SIZE))->ns) 57 + #define vec_labelset(VEC, SIZE) (&vec_ns((VEC), (SIZE))->labels) 58 + #define cleanup_domain_vec(V, L) cleanup_label_vec((V), (L)->size) 59 + 60 + struct aa_profile; 61 + #define VEC_FLAG_TERMINATE 1 62 + int aa_vec_unique(struct aa_profile **vec, int n, int flags); 63 + struct aa_label *aa_vec_find_or_create_label(struct aa_profile **vec, int len, 64 + gfp_t gfp); 65 + #define aa_sort_and_merge_vec(N, V) \ 66 + aa_sort_and_merge_profiles((N), (struct aa_profile **)(V)) 67 + 68 + 69 + /* struct aa_labelset - set of labels for a namespace 70 + * 71 + * Labels are reference counted; aa_labelset does not contribute to label 72 + * reference counts. Once a label's last refcount is put it is removed from 73 + * the set. 74 + */ 75 + struct aa_labelset { 76 + rwlock_t lock; 77 + 78 + struct rb_root root; 79 + }; 80 + 81 + #define __labelset_for_each(LS, N) \ 82 + for ((N) = rb_first(&(LS)->root); (N); (N) = rb_next(N)) 83 + 84 + void aa_labelset_destroy(struct aa_labelset *ls); 85 + void aa_labelset_init(struct aa_labelset *ls); 86 + 87 + 88 + enum label_flags { 89 + FLAG_HAT = 1, /* profile is a hat */ 90 + FLAG_UNCONFINED = 2, /* label unconfined only if all */ 91 + FLAG_NULL = 4, /* profile is null learning profile */ 92 + FLAG_IX_ON_NAME_ERROR = 8, /* fallback to ix on name lookup fail */ 93 + FLAG_IMMUTIBLE = 0x10, /* don't allow changes/replacement */ 94 + FLAG_USER_DEFINED = 0x20, /* user based profile - lower privs */ 95 + FLAG_NO_LIST_REF = 0x40, /* list doesn't keep profile ref */ 96 + FLAG_NS_COUNT = 0x80, /* carries NS ref count */ 97 + FLAG_IN_TREE = 0x100, /* label is in tree */ 98 + FLAG_PROFILE = 0x200, /* label is a profile */ 99 + FLAG_EXPLICIT = 0x400, /* explicit static label */ 100 + FLAG_STALE = 0x800, /* replaced/removed */ 101 + FLAG_RENAMED = 0x1000, /* label has renaming in it */ 102 + FLAG_REVOKED = 0x2000, /* label has revocation in it */ 103 + 104 + /* These flags must correspond with PATH_flags */ 105 + /* TODO: add new path flags */ 106 + }; 107 + 108 + struct aa_label; 109 + struct aa_proxy { 110 + struct kref count; 111 + struct aa_label __rcu *label; 112 + }; 113 + 114 + struct label_it { 115 + int i, j; 116 + }; 117 + 118 + /* struct aa_label - lazy labeling struct 119 + * @count: ref count of active users 120 + * @node: rbtree position 121 + * @rcu: rcu callback struct 122 + * @proxy: is set to the label that replaced this label 123 + * @hname: text representation of the label (MAYBE_NULL) 124 + * @flags: stale and other flags - values may change under label set lock 125 + * @secid: secid that references this label 126 + * @size: number of entries in @ent[] 127 + * @ent: set of profiles for label, actual size determined by @size 128 + */ 129 + struct aa_label { 130 + struct kref count; 131 + struct rb_node node; 132 + struct rcu_head rcu; 133 + struct aa_proxy *proxy; 134 + __counted char *hname; 135 + long flags; 136 + u32 secid; 137 + int size; 138 + struct aa_profile *vec[]; 139 + }; 140 + 141 + #define last_error(E, FN) \ 142 + do { \ 143 + int __subE = (FN); \ 144 + if (__subE) \ 145 + (E) = __subE; \ 146 + } while (0) 147 + 148 + #define label_isprofile(X) ((X)->flags & FLAG_PROFILE) 149 + #define label_unconfined(X) ((X)->flags & FLAG_UNCONFINED) 150 + #define unconfined(X) label_unconfined(X) 151 + #define label_is_stale(X) ((X)->flags & FLAG_STALE) 152 + #define __label_make_stale(X) ((X)->flags |= FLAG_STALE) 153 + #define labels_ns(X) (vec_ns(&((X)->vec[0]), (X)->size)) 154 + #define labels_set(X) (&labels_ns(X)->labels) 155 + #define labels_profile(X) ((X)->vec[(X)->size - 1]) 156 + 157 + 158 + int aa_label_next_confined(struct aa_label *l, int i); 159 + 160 + /* for each profile in a label */ 161 + #define label_for_each(I, L, P) \ 162 + for ((I).i = 0; ((P) = (L)->vec[(I).i]); ++((I).i)) 163 + 164 + /* assumes break/goto ended label_for_each */ 165 + #define label_for_each_cont(I, L, P) \ 166 + for (++((I).i); ((P) = (L)->vec[(I).i]); ++((I).i)) 167 + 168 + #define next_comb(I, L1, L2) \ 169 + do { \ 170 + (I).j++; \ 171 + if ((I).j >= (L2)->size) { \ 172 + (I).i++; \ 173 + (I).j = 0; \ 174 + } \ 175 + } while (0) 176 + 177 + 178 + /* for each combination of P1 in L1, and P2 in L2 */ 179 + #define label_for_each_comb(I, L1, L2, P1, P2) \ 180 + for ((I).i = (I).j = 0; \ 181 + ((P1) = (L1)->vec[(I).i]) && ((P2) = (L2)->vec[(I).j]); \ 182 + (I) = next_comb(I, L1, L2)) 183 + 184 + #define fn_for_each_comb(L1, L2, P1, P2, FN) \ 185 + ({ \ 186 + struct label_it i; \ 187 + int __E = 0; \ 188 + label_for_each_comb(i, (L1), (L2), (P1), (P2)) { \ 189 + last_error(__E, (FN)); \ 190 + } \ 191 + __E; \ 192 + }) 193 + 194 + /* for each profile that is enforcing confinement in a label */ 195 + #define label_for_each_confined(I, L, P) \ 196 + for ((I).i = aa_label_next_confined((L), 0); \ 197 + ((P) = (L)->vec[(I).i]); \ 198 + (I).i = aa_label_next_confined((L), (I).i + 1)) 199 + 200 + #define label_for_each_in_merge(I, A, B, P) \ 201 + for ((I).i = (I).j = 0; \ 202 + ((P) = aa_label_next_in_merge(&(I), (A), (B))); \ 203 + ) 204 + 205 + #define label_for_each_not_in_set(I, SET, SUB, P) \ 206 + for ((I).i = (I).j = 0; \ 207 + ((P) = __aa_label_next_not_in_set(&(I), (SET), (SUB))); \ 208 + ) 209 + 210 + #define next_in_ns(i, NS, L) \ 211 + ({ \ 212 + typeof(i) ___i = (i); \ 213 + while ((L)->vec[___i] && (L)->vec[___i]->ns != (NS)) \ 214 + (___i)++; \ 215 + (___i); \ 216 + }) 217 + 218 + #define label_for_each_in_ns(I, NS, L, P) \ 219 + for ((I).i = next_in_ns(0, (NS), (L)); \ 220 + ((P) = (L)->vec[(I).i]); \ 221 + (I).i = next_in_ns((I).i + 1, (NS), (L))) 222 + 223 + #define fn_for_each_in_ns(L, P, FN) \ 224 + ({ \ 225 + struct label_it __i; \ 226 + struct aa_ns *__ns = labels_ns(L); \ 227 + int __E = 0; \ 228 + label_for_each_in_ns(__i, __ns, (L), (P)) { \ 229 + last_error(__E, (FN)); \ 230 + } \ 231 + __E; \ 232 + }) 233 + 234 + 235 + #define fn_for_each_XXX(L, P, FN, ...) \ 236 + ({ \ 237 + struct label_it i; \ 238 + int __E = 0; \ 239 + label_for_each ## __VA_ARGS__(i, (L), (P)) { \ 240 + last_error(__E, (FN)); \ 241 + } \ 242 + __E; \ 243 + }) 244 + 245 + #define fn_for_each(L, P, FN) fn_for_each_XXX(L, P, FN) 246 + #define fn_for_each_confined(L, P, FN) fn_for_each_XXX(L, P, FN, _confined) 247 + 248 + #define fn_for_each2_XXX(L1, L2, P, FN, ...) \ 249 + ({ \ 250 + struct label_it i; \ 251 + int __E = 0; \ 252 + label_for_each ## __VA_ARGS__(i, (L1), (L2), (P)) { \ 253 + last_error(__E, (FN)); \ 254 + } \ 255 + __E; \ 256 + }) 257 + 258 + #define fn_for_each_in_merge(L1, L2, P, FN) \ 259 + fn_for_each2_XXX((L1), (L2), P, FN, _in_merge) 260 + #define fn_for_each_not_in_set(L1, L2, P, FN) \ 261 + fn_for_each2_XXX((L1), (L2), P, FN, _not_in_set) 262 + 263 + #define LABEL_MEDIATES(L, C) \ 264 + ({ \ 265 + struct aa_profile *profile; \ 266 + struct label_it i; \ 267 + int ret = 0; \ 268 + label_for_each(i, (L), profile) { \ 269 + if (PROFILE_MEDIATES(profile, (C))) { \ 270 + ret = 1; \ 271 + break; \ 272 + } \ 273 + } \ 274 + ret; \ 275 + }) 276 + 277 + 278 + void aa_labelset_destroy(struct aa_labelset *ls); 279 + void aa_labelset_init(struct aa_labelset *ls); 280 + void __aa_labelset_update_subtree(struct aa_ns *ns); 281 + 282 + void aa_label_free(struct aa_label *label); 283 + void aa_label_kref(struct kref *kref); 284 + bool aa_label_init(struct aa_label *label, int size); 285 + struct aa_label *aa_label_alloc(int size, struct aa_proxy *proxy, gfp_t gfp); 286 + 287 + bool aa_label_is_subset(struct aa_label *set, struct aa_label *sub); 288 + struct aa_profile *__aa_label_next_not_in_set(struct label_it *I, 289 + struct aa_label *set, 290 + struct aa_label *sub); 291 + bool aa_label_remove(struct aa_label *label); 292 + struct aa_label *aa_label_insert(struct aa_labelset *ls, struct aa_label *l); 293 + bool aa_label_replace(struct aa_label *old, struct aa_label *new); 294 + bool aa_label_make_newest(struct aa_labelset *ls, struct aa_label *old, 295 + struct aa_label *new); 296 + 297 + struct aa_label *aa_label_find(struct aa_label *l); 298 + 299 + struct aa_profile *aa_label_next_in_merge(struct label_it *I, 300 + struct aa_label *a, 301 + struct aa_label *b); 302 + struct aa_label *aa_label_find_merge(struct aa_label *a, struct aa_label *b); 303 + struct aa_label *aa_label_merge(struct aa_label *a, struct aa_label *b, 304 + gfp_t gfp); 305 + 306 + 307 + bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp); 308 + 309 + #define FLAGS_NONE 0 310 + #define FLAG_SHOW_MODE 1 311 + #define FLAG_VIEW_SUBNS 2 312 + #define FLAG_HIDDEN_UNCONFINED 4 313 + int aa_label_snxprint(char *str, size_t size, struct aa_ns *view, 314 + struct aa_label *label, int flags); 315 + int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label, 316 + int flags, gfp_t gfp); 317 + int aa_label_acntsxprint(char __counted **strp, struct aa_ns *ns, 318 + struct aa_label *label, int flags, gfp_t gfp); 319 + void aa_label_xaudit(struct audit_buffer *ab, struct aa_ns *ns, 320 + struct aa_label *label, int flags, gfp_t gfp); 321 + void aa_label_seq_xprint(struct seq_file *f, struct aa_ns *ns, 322 + struct aa_label *label, int flags, gfp_t gfp); 323 + void aa_label_xprintk(struct aa_ns *ns, struct aa_label *label, int flags, 324 + gfp_t gfp); 325 + void aa_label_audit(struct audit_buffer *ab, struct aa_label *label, gfp_t gfp); 326 + void aa_label_seq_print(struct seq_file *f, struct aa_label *label, gfp_t gfp); 327 + void aa_label_printk(struct aa_label *label, gfp_t gfp); 328 + 329 + struct aa_label *aa_label_parse(struct aa_label *base, const char *str, 330 + gfp_t gfp, bool create, bool force_stack); 331 + 332 + 333 + struct aa_perms; 334 + int aa_label_match(struct aa_profile *profile, struct aa_label *label, 335 + unsigned int state, bool subns, u32 request, 336 + struct aa_perms *perms); 337 + 338 + 339 + /** 340 + * __aa_get_label - get a reference count to uncounted label reference 341 + * @l: reference to get a count on 342 + * 343 + * Returns: pointer to reference OR NULL if race is lost and reference is 344 + * being repeated. 345 + * Requires: lock held, and the return code MUST be checked 346 + */ 347 + static inline struct aa_label *__aa_get_label(struct aa_label *l) 348 + { 349 + if (l && kref_get_unless_zero(&l->count)) 350 + return l; 351 + 352 + return NULL; 353 + } 354 + 355 + static inline struct aa_label *aa_get_label(struct aa_label *l) 356 + { 357 + if (l) 358 + kref_get(&(l->count)); 359 + 360 + return l; 361 + } 362 + 363 + 364 + /** 365 + * aa_get_label_rcu - increment refcount on a label that can be replaced 366 + * @l: pointer to label that can be replaced (NOT NULL) 367 + * 368 + * Returns: pointer to a refcounted label. 369 + * else NULL if no label 370 + */ 371 + static inline struct aa_label *aa_get_label_rcu(struct aa_label __rcu **l) 372 + { 373 + struct aa_label *c; 374 + 375 + rcu_read_lock(); 376 + do { 377 + c = rcu_dereference(*l); 378 + } while (c && !kref_get_unless_zero(&c->count)); 379 + rcu_read_unlock(); 380 + 381 + return c; 382 + } 383 + 384 + /** 385 + * aa_get_newest_label - find the newest version of @l 386 + * @l: the label to check for newer versions of 387 + * 388 + * Returns: refcounted newest version of @l taking into account 389 + * replacement, renames and removals 390 + * return @l. 391 + */ 392 + static inline struct aa_label *aa_get_newest_label(struct aa_label *l) 393 + { 394 + if (!l) 395 + return NULL; 396 + 397 + if (label_is_stale(l)) { 398 + struct aa_label *tmp; 399 + 400 + AA_BUG(!l->proxy); 401 + AA_BUG(!l->proxy->label); 402 + /* BUG: only way this can happen is @l ref count and its 403 + * replacement count have gone to 0 and are on their way 404 + * to destruction. ie. we have a refcounting error 405 + */ 406 + tmp = aa_get_label_rcu(&l->proxy->label); 407 + AA_BUG(!tmp); 408 + 409 + return tmp; 410 + } 411 + 412 + return aa_get_label(l); 413 + } 414 + 415 + static inline void aa_put_label(struct aa_label *l) 416 + { 417 + if (l) 418 + kref_put(&l->count, aa_label_kref); 419 + } 420 + 421 + 422 + struct aa_proxy *aa_alloc_proxy(struct aa_label *l, gfp_t gfp); 423 + void aa_proxy_kref(struct kref *kref); 424 + 425 + static inline struct aa_proxy *aa_get_proxy(struct aa_proxy *proxy) 426 + { 427 + if (proxy) 428 + kref_get(&(proxy->count)); 429 + 430 + return proxy; 431 + } 432 + 433 + static inline void aa_put_proxy(struct aa_proxy *proxy) 434 + { 435 + if (proxy) 436 + kref_put(&proxy->count, aa_proxy_kref); 437 + } 438 + 439 + void __aa_proxy_redirect(struct aa_label *orig, struct aa_label *new); 440 + 441 + #endif /* __AA_LABEL_H */
+2120
security/apparmor/label.c
··· 1 + /* 2 + * AppArmor security module 3 + * 4 + * This file contains AppArmor label definitions 5 + * 6 + * Copyright 2017 Canonical Ltd. 7 + * 8 + * This program is free software; you can redistribute it and/or 9 + * modify it under the terms of the GNU General Public License as 10 + * published by the Free Software Foundation, version 2 of the 11 + * License. 12 + */ 13 + 14 + #include <linux/audit.h> 15 + #include <linux/seq_file.h> 16 + #include <linux/sort.h> 17 + 18 + #include "include/apparmor.h" 19 + #include "include/context.h" 20 + #include "include/label.h" 21 + #include "include/policy.h" 22 + #include "include/secid.h" 23 + 24 + 25 + /* 26 + * the aa_label represents the set of profiles confining an object 27 + * 28 + * Labels maintain a reference count to the set of pointers they reference 29 + * Labels are ref counted by 30 + * tasks and object via the security field/security context off the field 31 + * code - will take a ref count on a label if it needs the label 32 + * beyond what is possible with an rcu_read_lock. 33 + * profiles - each profile is a label 34 + * secids - a pinned secid will keep a refcount of the label it is 35 + * referencing 36 + * objects - inode, files, sockets, ... 37 + * 38 + * Labels are not ref counted by the label set, so they maybe removed and 39 + * freed when no longer in use. 40 + * 41 + */ 42 + 43 + #define PROXY_POISON 97 44 + #define LABEL_POISON 100 45 + 46 + static void free_proxy(struct aa_proxy *proxy) 47 + { 48 + if (proxy) { 49 + /* p->label will not updated any more as p is dead */ 50 + aa_put_label(rcu_dereference_protected(proxy->label, true)); 51 + memset(proxy, 0, sizeof(*proxy)); 52 + proxy->label = (struct aa_label *) PROXY_POISON; 53 + kfree(proxy); 54 + } 55 + } 56 + 57 + void aa_proxy_kref(struct kref *kref) 58 + { 59 + struct aa_proxy *proxy = container_of(kref, struct aa_proxy, count); 60 + 61 + free_proxy(proxy); 62 + } 63 + 64 + struct aa_proxy *aa_alloc_proxy(struct aa_label *label, gfp_t gfp) 65 + { 66 + struct aa_proxy *new; 67 + 68 + new = kzalloc(sizeof(struct aa_proxy), gfp); 69 + if (new) { 70 + kref_init(&new->count); 71 + rcu_assign_pointer(new->label, aa_get_label(label)); 72 + } 73 + return new; 74 + } 75 + 76 + /* requires profile list write lock held */ 77 + void __aa_proxy_redirect(struct aa_label *orig, struct aa_label *new) 78 + { 79 + struct aa_label *tmp; 80 + 81 + AA_BUG(!orig); 82 + AA_BUG(!new); 83 + AA_BUG(!write_is_locked(&labels_set(orig)->lock)); 84 + 85 + tmp = rcu_dereference_protected(orig->proxy->label, 86 + &labels_ns(orig)->lock); 87 + rcu_assign_pointer(orig->proxy->label, aa_get_label(new)); 88 + orig->flags |= FLAG_STALE; 89 + aa_put_label(tmp); 90 + } 91 + 92 + static void __proxy_share(struct aa_label *old, struct aa_label *new) 93 + { 94 + struct aa_proxy *proxy = new->proxy; 95 + 96 + new->proxy = aa_get_proxy(old->proxy); 97 + __aa_proxy_redirect(old, new); 98 + aa_put_proxy(proxy); 99 + } 100 + 101 + 102 + /** 103 + * ns_cmp - compare ns for label set ordering 104 + * @a: ns to compare (NOT NULL) 105 + * @b: ns to compare (NOT NULL) 106 + * 107 + * Returns: <0 if a < b 108 + * ==0 if a == b 109 + * >0 if a > b 110 + */ 111 + static int ns_cmp(struct aa_ns *a, struct aa_ns *b) 112 + { 113 + int res; 114 + 115 + AA_BUG(!a); 116 + AA_BUG(!b); 117 + AA_BUG(!a->base.hname); 118 + AA_BUG(!b->base.hname); 119 + 120 + if (a == b) 121 + return 0; 122 + 123 + res = a->level - b->level; 124 + if (res) 125 + return res; 126 + 127 + return strcmp(a->base.hname, b->base.hname); 128 + } 129 + 130 + /** 131 + * profile_cmp - profile comparision for set ordering 132 + * @a: profile to compare (NOT NULL) 133 + * @b: profile to compare (NOT NULL) 134 + * 135 + * Returns: <0 if a < b 136 + * ==0 if a == b 137 + * >0 if a > b 138 + */ 139 + static int profile_cmp(struct aa_profile *a, struct aa_profile *b) 140 + { 141 + int res; 142 + 143 + AA_BUG(!a); 144 + AA_BUG(!b); 145 + AA_BUG(!a->ns); 146 + AA_BUG(!b->ns); 147 + AA_BUG(!a->base.hname); 148 + AA_BUG(!b->base.hname); 149 + 150 + if (a == b || a->base.hname == b->base.hname) 151 + return 0; 152 + res = ns_cmp(a->ns, b->ns); 153 + if (res) 154 + return res; 155 + 156 + return strcmp(a->base.hname, b->base.hname); 157 + } 158 + 159 + /** 160 + * vec_cmp - label comparision for set ordering 161 + * @a: label to compare (NOT NULL) 162 + * @vec: vector of profiles to compare (NOT NULL) 163 + * @n: length of @vec 164 + * 165 + * Returns: <0 if a < vec 166 + * ==0 if a == vec 167 + * >0 if a > vec 168 + */ 169 + static int vec_cmp(struct aa_profile **a, int an, struct aa_profile **b, int bn) 170 + { 171 + int i; 172 + 173 + AA_BUG(!a); 174 + AA_BUG(!*a); 175 + AA_BUG(!b); 176 + AA_BUG(!*b); 177 + AA_BUG(an <= 0); 178 + AA_BUG(bn <= 0); 179 + 180 + for (i = 0; i < an && i < bn; i++) { 181 + int res = profile_cmp(a[i], b[i]); 182 + 183 + if (res != 0) 184 + return res; 185 + } 186 + 187 + return an - bn; 188 + } 189 + 190 + static bool vec_is_stale(struct aa_profile **vec, int n) 191 + { 192 + int i; 193 + 194 + AA_BUG(!vec); 195 + 196 + for (i = 0; i < n; i++) { 197 + if (profile_is_stale(vec[i])) 198 + return true; 199 + } 200 + 201 + return false; 202 + } 203 + 204 + static bool vec_unconfined(struct aa_profile **vec, int n) 205 + { 206 + int i; 207 + 208 + AA_BUG(!vec); 209 + 210 + for (i = 0; i < n; i++) { 211 + if (!profile_unconfined(vec[i])) 212 + return false; 213 + } 214 + 215 + return true; 216 + } 217 + 218 + static int sort_cmp(const void *a, const void *b) 219 + { 220 + return profile_cmp(*(struct aa_profile **)a, *(struct aa_profile **)b); 221 + } 222 + 223 + /* 224 + * assumes vec is sorted 225 + * Assumes @vec has null terminator at vec[n], and will null terminate 226 + * vec[n - dups] 227 + */ 228 + static inline int unique(struct aa_profile **vec, int n) 229 + { 230 + int i, pos, dups = 0; 231 + 232 + AA_BUG(n < 1); 233 + AA_BUG(!vec); 234 + 235 + pos = 0; 236 + for (i = 1; i < n; i++) { 237 + int res = profile_cmp(vec[pos], vec[i]); 238 + 239 + AA_BUG(res > 0, "vec not sorted"); 240 + if (res == 0) { 241 + /* drop duplicate */ 242 + aa_put_profile(vec[i]); 243 + dups++; 244 + continue; 245 + } 246 + pos++; 247 + if (dups) 248 + vec[pos] = vec[i]; 249 + } 250 + 251 + AA_BUG(dups < 0); 252 + 253 + return dups; 254 + } 255 + 256 + /** 257 + * aa_vec_unique - canonical sort and unique a list of profiles 258 + * @n: number of refcounted profiles in the list (@n > 0) 259 + * @vec: list of profiles to sort and merge 260 + * 261 + * Returns: the number of duplicates eliminated == references put 262 + * 263 + * If @flags & VEC_FLAG_TERMINATE @vec has null terminator at vec[n], and will 264 + * null terminate vec[n - dups] 265 + */ 266 + int aa_vec_unique(struct aa_profile **vec, int n, int flags) 267 + { 268 + int i, dups = 0; 269 + 270 + AA_BUG(n < 1); 271 + AA_BUG(!vec); 272 + 273 + /* vecs are usually small and inorder, have a fallback for larger */ 274 + if (n > 8) { 275 + sort(vec, n, sizeof(struct aa_profile *), sort_cmp, NULL); 276 + dups = unique(vec, n); 277 + goto out; 278 + } 279 + 280 + /* insertion sort + unique in one */ 281 + for (i = 1; i < n; i++) { 282 + struct aa_profile *tmp = vec[i]; 283 + int pos, j; 284 + 285 + for (pos = i - 1 - dups; pos >= 0; pos--) { 286 + int res = profile_cmp(vec[pos], tmp); 287 + 288 + if (res == 0) { 289 + /* drop duplicate entry */ 290 + aa_put_profile(tmp); 291 + dups++; 292 + goto continue_outer; 293 + } else if (res < 0) 294 + break; 295 + } 296 + /* pos is at entry < tmp, or index -1. Set to insert pos */ 297 + pos++; 298 + 299 + for (j = i - dups; j > pos; j--) 300 + vec[j] = vec[j - 1]; 301 + vec[pos] = tmp; 302 + continue_outer: 303 + ; 304 + } 305 + 306 + AA_BUG(dups < 0); 307 + 308 + out: 309 + if (flags & VEC_FLAG_TERMINATE) 310 + vec[n - dups] = NULL; 311 + 312 + return dups; 313 + } 314 + 315 + 316 + static void label_destroy(struct aa_label *label) 317 + { 318 + struct aa_label *tmp; 319 + 320 + AA_BUG(!label); 321 + 322 + if (!label_isprofile(label)) { 323 + struct aa_profile *profile; 324 + struct label_it i; 325 + 326 + aa_put_str(label->hname); 327 + 328 + label_for_each(i, label, profile) { 329 + aa_put_profile(profile); 330 + label->vec[i.i] = (struct aa_profile *) 331 + (LABEL_POISON + (long) i.i); 332 + } 333 + } 334 + 335 + if (rcu_dereference_protected(label->proxy->label, true) == label) 336 + rcu_assign_pointer(label->proxy->label, NULL); 337 + 338 + aa_free_secid(label->secid); 339 + 340 + tmp = rcu_dereference_protected(label->proxy->label, true); 341 + if (tmp == label) 342 + rcu_assign_pointer(label->proxy->label, NULL); 343 + 344 + aa_put_proxy(label->proxy); 345 + label->proxy = (struct aa_proxy *) PROXY_POISON + 1; 346 + } 347 + 348 + void aa_label_free(struct aa_label *label) 349 + { 350 + if (!label) 351 + return; 352 + 353 + label_destroy(label); 354 + kfree(label); 355 + } 356 + 357 + static void label_free_switch(struct aa_label *label) 358 + { 359 + if (label->flags & FLAG_NS_COUNT) 360 + aa_free_ns(labels_ns(label)); 361 + else if (label_isprofile(label)) 362 + aa_free_profile(labels_profile(label)); 363 + else 364 + aa_label_free(label); 365 + } 366 + 367 + static void label_free_rcu(struct rcu_head *head) 368 + { 369 + struct aa_label *label = container_of(head, struct aa_label, rcu); 370 + 371 + if (label->flags & FLAG_IN_TREE) 372 + (void) aa_label_remove(label); 373 + label_free_switch(label); 374 + } 375 + 376 + void aa_label_kref(struct kref *kref) 377 + { 378 + struct aa_label *label = container_of(kref, struct aa_label, count); 379 + struct aa_ns *ns = labels_ns(label); 380 + 381 + if (!ns) { 382 + /* never live, no rcu callback needed, just using the fn */ 383 + label_free_switch(label); 384 + return; 385 + } 386 + /* TODO: update labels_profile macro so it works here */ 387 + AA_BUG(label_isprofile(label) && 388 + on_list_rcu(&label->vec[0]->base.profiles)); 389 + AA_BUG(label_isprofile(label) && 390 + on_list_rcu(&label->vec[0]->base.list)); 391 + 392 + /* TODO: if compound label and not stale add to reclaim cache */ 393 + call_rcu(&label->rcu, label_free_rcu); 394 + } 395 + 396 + static void label_free_or_put_new(struct aa_label *label, struct aa_label *new) 397 + { 398 + if (label != new) 399 + /* need to free directly to break circular ref with proxy */ 400 + aa_label_free(new); 401 + else 402 + aa_put_label(new); 403 + } 404 + 405 + bool aa_label_init(struct aa_label *label, int size) 406 + { 407 + AA_BUG(!label); 408 + AA_BUG(size < 1); 409 + 410 + label->secid = aa_alloc_secid(); 411 + if (label->secid == AA_SECID_INVALID) 412 + return false; 413 + 414 + label->size = size; /* doesn't include null */ 415 + label->vec[size] = NULL; /* null terminate */ 416 + kref_init(&label->count); 417 + RB_CLEAR_NODE(&label->node); 418 + 419 + return true; 420 + } 421 + 422 + /** 423 + * aa_label_alloc - allocate a label with a profile vector of @size length 424 + * @size: size of profile vector in the label 425 + * @proxy: proxy to use OR null if to allocate a new one 426 + * @gfp: memory allocation type 427 + * 428 + * Returns: new label 429 + * else NULL if failed 430 + */ 431 + struct aa_label *aa_label_alloc(int size, struct aa_proxy *proxy, gfp_t gfp) 432 + { 433 + struct aa_label *new; 434 + 435 + AA_BUG(size < 1); 436 + 437 + /* + 1 for null terminator entry on vec */ 438 + new = kzalloc(sizeof(*new) + sizeof(struct aa_profile *) * (size + 1), 439 + gfp); 440 + AA_DEBUG("%s (%p)\n", __func__, new); 441 + if (!new) 442 + goto fail; 443 + 444 + if (!aa_label_init(new, size)) 445 + goto fail; 446 + 447 + if (!proxy) { 448 + proxy = aa_alloc_proxy(new, gfp); 449 + if (!proxy) 450 + goto fail; 451 + } else 452 + aa_get_proxy(proxy); 453 + /* just set new's proxy, don't redirect proxy here if it was passed in*/ 454 + new->proxy = proxy; 455 + 456 + return new; 457 + 458 + fail: 459 + kfree(new); 460 + 461 + return NULL; 462 + } 463 + 464 + 465 + /** 466 + * label_cmp - label comparision for set ordering 467 + * @a: label to compare (NOT NULL) 468 + * @b: label to compare (NOT NULL) 469 + * 470 + * Returns: <0 if a < b 471 + * ==0 if a == b 472 + * >0 if a > b 473 + */ 474 + static int label_cmp(struct aa_label *a, struct aa_label *b) 475 + { 476 + AA_BUG(!b); 477 + 478 + if (a == b) 479 + return 0; 480 + 481 + return vec_cmp(a->vec, a->size, b->vec, b->size); 482 + } 483 + 484 + /* helper fn for label_for_each_confined */ 485 + int aa_label_next_confined(struct aa_label *label, int i) 486 + { 487 + AA_BUG(!label); 488 + AA_BUG(i < 0); 489 + 490 + for (; i < label->size; i++) { 491 + if (!profile_unconfined(label->vec[i])) 492 + return i; 493 + } 494 + 495 + return i; 496 + } 497 + 498 + /** 499 + * aa_label_next_not_in_set - return the next profile of @sub not in @set 500 + * @I: label iterator 501 + * @set: label to test against 502 + * @sub: label to if is subset of @set 503 + * 504 + * Returns: profile in @sub that is not in @set, with iterator set pos after 505 + * else NULL if @sub is a subset of @set 506 + */ 507 + struct aa_profile *__aa_label_next_not_in_set(struct label_it *I, 508 + struct aa_label *set, 509 + struct aa_label *sub) 510 + { 511 + AA_BUG(!set); 512 + AA_BUG(!I); 513 + AA_BUG(I->i < 0); 514 + AA_BUG(I->i > set->size); 515 + AA_BUG(!sub); 516 + AA_BUG(I->j < 0); 517 + AA_BUG(I->j > sub->size); 518 + 519 + while (I->j < sub->size && I->i < set->size) { 520 + int res = profile_cmp(sub->vec[I->j], set->vec[I->i]); 521 + 522 + if (res == 0) { 523 + (I->j)++; 524 + (I->i)++; 525 + } else if (res > 0) 526 + (I->i)++; 527 + else 528 + return sub->vec[(I->j)++]; 529 + } 530 + 531 + if (I->j < sub->size) 532 + return sub->vec[(I->j)++]; 533 + 534 + return NULL; 535 + } 536 + 537 + /** 538 + * aa_label_is_subset - test if @sub is a subset of @set 539 + * @set: label to test against 540 + * @sub: label to test if is subset of @set 541 + * 542 + * Returns: true if @sub is subset of @set 543 + * else false 544 + */ 545 + bool aa_label_is_subset(struct aa_label *set, struct aa_label *sub) 546 + { 547 + struct label_it i = { }; 548 + 549 + AA_BUG(!set); 550 + AA_BUG(!sub); 551 + 552 + if (sub == set) 553 + return true; 554 + 555 + return __aa_label_next_not_in_set(&i, set, sub) == NULL; 556 + } 557 + 558 + 559 + 560 + /** 561 + * __label_remove - remove @label from the label set 562 + * @l: label to remove 563 + * @new: label to redirect to 564 + * 565 + * Requires: labels_set(@label)->lock write_lock 566 + * Returns: true if the label was in the tree and removed 567 + */ 568 + static bool __label_remove(struct aa_label *label, struct aa_label *new) 569 + { 570 + struct aa_labelset *ls = labels_set(label); 571 + 572 + AA_BUG(!ls); 573 + AA_BUG(!label); 574 + AA_BUG(!write_is_locked(&ls->lock)); 575 + 576 + if (new) 577 + __aa_proxy_redirect(label, new); 578 + 579 + if (!label_is_stale(label)) 580 + __label_make_stale(label); 581 + 582 + if (label->flags & FLAG_IN_TREE) { 583 + rb_erase(&label->node, &ls->root); 584 + label->flags &= ~FLAG_IN_TREE; 585 + return true; 586 + } 587 + 588 + return false; 589 + } 590 + 591 + /** 592 + * __label_replace - replace @old with @new in label set 593 + * @old: label to remove from label set 594 + * @new: label to replace @old with 595 + * 596 + * Requires: labels_set(@old)->lock write_lock 597 + * valid ref count be held on @new 598 + * Returns: true if @old was in set and replaced by @new 599 + * 600 + * Note: current implementation requires label set be order in such a way 601 + * that @new directly replaces @old position in the set (ie. 602 + * using pointer comparison of the label address would not work) 603 + */ 604 + static bool __label_replace(struct aa_label *old, struct aa_label *new) 605 + { 606 + struct aa_labelset *ls = labels_set(old); 607 + 608 + AA_BUG(!ls); 609 + AA_BUG(!old); 610 + AA_BUG(!new); 611 + AA_BUG(!write_is_locked(&ls->lock)); 612 + AA_BUG(new->flags & FLAG_IN_TREE); 613 + 614 + if (!label_is_stale(old)) 615 + __label_make_stale(old); 616 + 617 + if (old->flags & FLAG_IN_TREE) { 618 + rb_replace_node(&old->node, &new->node, &ls->root); 619 + old->flags &= ~FLAG_IN_TREE; 620 + new->flags |= FLAG_IN_TREE; 621 + return true; 622 + } 623 + 624 + return false; 625 + } 626 + 627 + /** 628 + * __label_insert - attempt to insert @l into a label set 629 + * @ls: set of labels to insert @l into (NOT NULL) 630 + * @label: new label to insert (NOT NULL) 631 + * @replace: whether insertion should replace existing entry that is not stale 632 + * 633 + * Requires: @ls->lock 634 + * caller to hold a valid ref on l 635 + * if @replace is true l has a preallocated proxy associated 636 + * Returns: @l if successful in inserting @l - with additional refcount 637 + * else ref counted equivalent label that is already in the set, 638 + * the else condition only happens if @replace is false 639 + */ 640 + static struct aa_label *__label_insert(struct aa_labelset *ls, 641 + struct aa_label *label, bool replace) 642 + { 643 + struct rb_node **new, *parent = NULL; 644 + 645 + AA_BUG(!ls); 646 + AA_BUG(!label); 647 + AA_BUG(labels_set(label) != ls); 648 + AA_BUG(!write_is_locked(&ls->lock)); 649 + AA_BUG(label->flags & FLAG_IN_TREE); 650 + 651 + /* Figure out where to put new node */ 652 + new = &ls->root.rb_node; 653 + while (*new) { 654 + struct aa_label *this = rb_entry(*new, struct aa_label, node); 655 + int result = label_cmp(label, this); 656 + 657 + parent = *new; 658 + if (result == 0) { 659 + /* !__aa_get_label means queued for destruction, 660 + * so replace in place, however the label has 661 + * died before the replacement so do not share 662 + * the proxy 663 + */ 664 + if (!replace && !label_is_stale(this)) { 665 + if (__aa_get_label(this)) 666 + return this; 667 + } else 668 + __proxy_share(this, label); 669 + AA_BUG(!__label_replace(this, label)); 670 + return aa_get_label(label); 671 + } else if (result < 0) 672 + new = &((*new)->rb_left); 673 + else /* (result > 0) */ 674 + new = &((*new)->rb_right); 675 + } 676 + 677 + /* Add new node and rebalance tree. */ 678 + rb_link_node(&label->node, parent, new); 679 + rb_insert_color(&label->node, &ls->root); 680 + label->flags |= FLAG_IN_TREE; 681 + 682 + return aa_get_label(label); 683 + } 684 + 685 + /** 686 + * __vec_find - find label that matches @vec in label set 687 + * @vec: vec of profiles to find matching label for (NOT NULL) 688 + * @n: length of @vec 689 + * 690 + * Requires: @vec_labelset(vec) lock held 691 + * caller to hold a valid ref on l 692 + * 693 + * Returns: ref counted @label if matching label is in tree 694 + * ref counted label that is equiv to @l in tree 695 + * else NULL if @vec equiv is not in tree 696 + */ 697 + static struct aa_label *__vec_find(struct aa_profile **vec, int n) 698 + { 699 + struct rb_node *node; 700 + 701 + AA_BUG(!vec); 702 + AA_BUG(!*vec); 703 + AA_BUG(n <= 0); 704 + 705 + node = vec_labelset(vec, n)->root.rb_node; 706 + while (node) { 707 + struct aa_label *this = rb_entry(node, struct aa_label, node); 708 + int result = vec_cmp(this->vec, this->size, vec, n); 709 + 710 + if (result > 0) 711 + node = node->rb_left; 712 + else if (result < 0) 713 + node = node->rb_right; 714 + else 715 + return __aa_get_label(this); 716 + } 717 + 718 + return NULL; 719 + } 720 + 721 + /** 722 + * __label_find - find label @label in label set 723 + * @label: label to find (NOT NULL) 724 + * 725 + * Requires: labels_set(@label)->lock held 726 + * caller to hold a valid ref on l 727 + * 728 + * Returns: ref counted @label if @label is in tree OR 729 + * ref counted label that is equiv to @label in tree 730 + * else NULL if @label or equiv is not in tree 731 + */ 732 + static struct aa_label *__label_find(struct aa_label *label) 733 + { 734 + AA_BUG(!label); 735 + 736 + return __vec_find(label->vec, label->size); 737 + } 738 + 739 + 740 + /** 741 + * aa_label_remove - remove a label from the labelset 742 + * @label: label to remove 743 + * 744 + * Returns: true if @label was removed from the tree 745 + * else @label was not in tree so it could not be removed 746 + */ 747 + bool aa_label_remove(struct aa_label *label) 748 + { 749 + struct aa_labelset *ls = labels_set(label); 750 + unsigned long flags; 751 + bool res; 752 + 753 + AA_BUG(!ls); 754 + 755 + write_lock_irqsave(&ls->lock, flags); 756 + res = __label_remove(label, ns_unconfined(labels_ns(label))); 757 + write_unlock_irqrestore(&ls->lock, flags); 758 + 759 + return res; 760 + } 761 + 762 + /** 763 + * aa_label_replace - replace a label @old with a new version @new 764 + * @old: label to replace 765 + * @new: label replacing @old 766 + * 767 + * Returns: true if @old was in tree and replaced 768 + * else @old was not in tree, and @new was not inserted 769 + */ 770 + bool aa_label_replace(struct aa_label *old, struct aa_label *new) 771 + { 772 + unsigned long flags; 773 + bool res; 774 + 775 + if (name_is_shared(old, new) && labels_ns(old) == labels_ns(new)) { 776 + write_lock_irqsave(&labels_set(old)->lock, flags); 777 + if (old->proxy != new->proxy) 778 + __proxy_share(old, new); 779 + else 780 + __aa_proxy_redirect(old, new); 781 + res = __label_replace(old, new); 782 + write_unlock_irqrestore(&labels_set(old)->lock, flags); 783 + } else { 784 + struct aa_label *l; 785 + struct aa_labelset *ls = labels_set(old); 786 + 787 + write_lock_irqsave(&ls->lock, flags); 788 + res = __label_remove(old, new); 789 + if (labels_ns(old) != labels_ns(new)) { 790 + write_unlock_irqrestore(&ls->lock, flags); 791 + ls = labels_set(new); 792 + write_lock_irqsave(&ls->lock, flags); 793 + } 794 + l = __label_insert(ls, new, true); 795 + res = (l == new); 796 + write_unlock_irqrestore(&ls->lock, flags); 797 + aa_put_label(l); 798 + } 799 + 800 + return res; 801 + } 802 + 803 + /** 804 + * vec_find - find label @l in label set 805 + * @vec: array of profiles to find equiv label for (NOT NULL) 806 + * @n: length of @vec 807 + * 808 + * Returns: refcounted label if @vec equiv is in tree 809 + * else NULL if @vec equiv is not in tree 810 + */ 811 + static struct aa_label *vec_find(struct aa_profile **vec, int n) 812 + { 813 + struct aa_labelset *ls; 814 + struct aa_label *label; 815 + unsigned long flags; 816 + 817 + AA_BUG(!vec); 818 + AA_BUG(!*vec); 819 + AA_BUG(n <= 0); 820 + 821 + ls = vec_labelset(vec, n); 822 + read_lock_irqsave(&ls->lock, flags); 823 + label = __vec_find(vec, n); 824 + read_unlock_irqrestore(&ls->lock, flags); 825 + 826 + return label; 827 + } 828 + 829 + /* requires sort and merge done first */ 830 + static struct aa_label *vec_create_and_insert_label(struct aa_profile **vec, 831 + int len, gfp_t gfp) 832 + { 833 + struct aa_label *label = NULL; 834 + struct aa_labelset *ls; 835 + unsigned long flags; 836 + struct aa_label *new; 837 + int i; 838 + 839 + AA_BUG(!vec); 840 + 841 + if (len == 1) 842 + return aa_get_label(&vec[0]->label); 843 + 844 + ls = labels_set(&vec[len - 1]->label); 845 + 846 + /* TODO: enable when read side is lockless 847 + * check if label exists before taking locks 848 + */ 849 + new = aa_label_alloc(len, NULL, gfp); 850 + if (!new) 851 + return NULL; 852 + 853 + for (i = 0; i < len; i++) 854 + new->vec[i] = aa_get_profile(vec[i]); 855 + 856 + write_lock_irqsave(&ls->lock, flags); 857 + label = __label_insert(ls, new, false); 858 + write_unlock_irqrestore(&ls->lock, flags); 859 + label_free_or_put_new(label, new); 860 + 861 + return label; 862 + } 863 + 864 + struct aa_label *aa_vec_find_or_create_label(struct aa_profile **vec, int len, 865 + gfp_t gfp) 866 + { 867 + struct aa_label *label = vec_find(vec, len); 868 + 869 + if (label) 870 + return label; 871 + 872 + return vec_create_and_insert_label(vec, len, gfp); 873 + } 874 + 875 + /** 876 + * aa_label_find - find label @label in label set 877 + * @label: label to find (NOT NULL) 878 + * 879 + * Requires: caller to hold a valid ref on l 880 + * 881 + * Returns: refcounted @label if @label is in tree 882 + * refcounted label that is equiv to @label in tree 883 + * else NULL if @label or equiv is not in tree 884 + */ 885 + struct aa_label *aa_label_find(struct aa_label *label) 886 + { 887 + AA_BUG(!label); 888 + 889 + return vec_find(label->vec, label->size); 890 + } 891 + 892 + 893 + /** 894 + * aa_label_insert - insert label @label into @ls or return existing label 895 + * @ls - labelset to insert @label into 896 + * @label - label to insert 897 + * 898 + * Requires: caller to hold a valid ref on @label 899 + * 900 + * Returns: ref counted @label if successful in inserting @label 901 + * else ref counted equivalent label that is already in the set 902 + */ 903 + struct aa_label *aa_label_insert(struct aa_labelset *ls, struct aa_label *label) 904 + { 905 + struct aa_label *l; 906 + unsigned long flags; 907 + 908 + AA_BUG(!ls); 909 + AA_BUG(!label); 910 + 911 + /* check if label exists before taking lock */ 912 + if (!label_is_stale(label)) { 913 + read_lock_irqsave(&ls->lock, flags); 914 + l = __label_find(label); 915 + read_unlock_irqrestore(&ls->lock, flags); 916 + if (l) 917 + return l; 918 + } 919 + 920 + write_lock_irqsave(&ls->lock, flags); 921 + l = __label_insert(ls, label, false); 922 + write_unlock_irqrestore(&ls->lock, flags); 923 + 924 + return l; 925 + } 926 + 927 + 928 + /** 929 + * aa_label_next_in_merge - find the next profile when merging @a and @b 930 + * @I: label iterator 931 + * @a: label to merge 932 + * @b: label to merge 933 + * 934 + * Returns: next profile 935 + * else null if no more profiles 936 + */ 937 + struct aa_profile *aa_label_next_in_merge(struct label_it *I, 938 + struct aa_label *a, 939 + struct aa_label *b) 940 + { 941 + AA_BUG(!a); 942 + AA_BUG(!b); 943 + AA_BUG(!I); 944 + AA_BUG(I->i < 0); 945 + AA_BUG(I->i > a->size); 946 + AA_BUG(I->j < 0); 947 + AA_BUG(I->j > b->size); 948 + 949 + if (I->i < a->size) { 950 + if (I->j < b->size) { 951 + int res = profile_cmp(a->vec[I->i], b->vec[I->j]); 952 + 953 + if (res > 0) 954 + return b->vec[(I->j)++]; 955 + if (res == 0) 956 + (I->j)++; 957 + } 958 + 959 + return a->vec[(I->i)++]; 960 + } 961 + 962 + if (I->j < b->size) 963 + return b->vec[(I->j)++]; 964 + 965 + return NULL; 966 + } 967 + 968 + /** 969 + * label_merge_cmp - cmp of @a merging with @b against @z for set ordering 970 + * @a: label to merge then compare (NOT NULL) 971 + * @b: label to merge then compare (NOT NULL) 972 + * @z: label to compare merge against (NOT NULL) 973 + * 974 + * Assumes: using the most recent versions of @a, @b, and @z 975 + * 976 + * Returns: <0 if a < b 977 + * ==0 if a == b 978 + * >0 if a > b 979 + */ 980 + static int label_merge_cmp(struct aa_label *a, struct aa_label *b, 981 + struct aa_label *z) 982 + { 983 + struct aa_profile *p = NULL; 984 + struct label_it i = { }; 985 + int k; 986 + 987 + AA_BUG(!a); 988 + AA_BUG(!b); 989 + AA_BUG(!z); 990 + 991 + for (k = 0; 992 + k < z->size && (p = aa_label_next_in_merge(&i, a, b)); 993 + k++) { 994 + int res = profile_cmp(p, z->vec[k]); 995 + 996 + if (res != 0) 997 + return res; 998 + } 999 + 1000 + if (p) 1001 + return 1; 1002 + else if (k < z->size) 1003 + return -1; 1004 + return 0; 1005 + } 1006 + 1007 + /** 1008 + * label_merge_insert - create a new label by merging @a and @b 1009 + * @new: preallocated label to merge into (NOT NULL) 1010 + * @a: label to merge with @b (NOT NULL) 1011 + * @b: label to merge with @a (NOT NULL) 1012 + * 1013 + * Requires: preallocated proxy 1014 + * 1015 + * Returns: ref counted label either @new if merge is unique 1016 + * @a if @b is a subset of @a 1017 + * @b if @a is a subset of @b 1018 + * 1019 + * NOTE: will not use @new if the merge results in @new == @a or @b 1020 + * 1021 + * Must be used within labelset write lock to avoid racing with 1022 + * setting labels stale. 1023 + */ 1024 + static struct aa_label *label_merge_insert(struct aa_label *new, 1025 + struct aa_label *a, 1026 + struct aa_label *b) 1027 + { 1028 + struct aa_label *label; 1029 + struct aa_labelset *ls; 1030 + struct aa_profile *next; 1031 + struct label_it i; 1032 + unsigned long flags; 1033 + int k = 0, invcount = 0; 1034 + bool stale = false; 1035 + 1036 + AA_BUG(!a); 1037 + AA_BUG(a->size < 0); 1038 + AA_BUG(!b); 1039 + AA_BUG(b->size < 0); 1040 + AA_BUG(!new); 1041 + AA_BUG(new->size < a->size + b->size); 1042 + 1043 + label_for_each_in_merge(i, a, b, next) { 1044 + AA_BUG(!next); 1045 + if (profile_is_stale(next)) { 1046 + new->vec[k] = aa_get_newest_profile(next); 1047 + AA_BUG(!new->vec[k]->label.proxy); 1048 + AA_BUG(!new->vec[k]->label.proxy->label); 1049 + if (next->label.proxy != new->vec[k]->label.proxy) 1050 + invcount++; 1051 + k++; 1052 + stale = true; 1053 + } else 1054 + new->vec[k++] = aa_get_profile(next); 1055 + } 1056 + /* set to actual size which is <= allocated len */ 1057 + new->size = k; 1058 + new->vec[k] = NULL; 1059 + 1060 + if (invcount) { 1061 + new->size -= aa_vec_unique(&new->vec[0], new->size, 1062 + VEC_FLAG_TERMINATE); 1063 + /* TODO: deal with reference labels */ 1064 + if (new->size == 1) { 1065 + label = aa_get_label(&new->vec[0]->label); 1066 + return label; 1067 + } 1068 + } else if (!stale) { 1069 + /* 1070 + * merge could be same as a || b, note: it is not possible 1071 + * for new->size == a->size == b->size unless a == b 1072 + */ 1073 + if (k == a->size) 1074 + return aa_get_label(a); 1075 + else if (k == b->size) 1076 + return aa_get_label(b); 1077 + } 1078 + if (vec_unconfined(new->vec, new->size)) 1079 + new->flags |= FLAG_UNCONFINED; 1080 + ls = labels_set(new); 1081 + write_lock_irqsave(&ls->lock, flags); 1082 + label = __label_insert(labels_set(new), new, false); 1083 + write_unlock_irqrestore(&ls->lock, flags); 1084 + 1085 + return label; 1086 + } 1087 + 1088 + /** 1089 + * labelset_of_merge - find which labelset a merged label should be inserted 1090 + * @a: label to merge and insert 1091 + * @b: label to merge and insert 1092 + * 1093 + * Returns: labelset that the merged label should be inserted into 1094 + */ 1095 + static struct aa_labelset *labelset_of_merge(struct aa_label *a, 1096 + struct aa_label *b) 1097 + { 1098 + struct aa_ns *nsa = labels_ns(a); 1099 + struct aa_ns *nsb = labels_ns(b); 1100 + 1101 + if (ns_cmp(nsa, nsb) <= 0) 1102 + return &nsa->labels; 1103 + return &nsb->labels; 1104 + } 1105 + 1106 + /** 1107 + * __label_find_merge - find label that is equiv to merge of @a and @b 1108 + * @ls: set of labels to search (NOT NULL) 1109 + * @a: label to merge with @b (NOT NULL) 1110 + * @b: label to merge with @a (NOT NULL) 1111 + * 1112 + * Requires: ls->lock read_lock held 1113 + * 1114 + * Returns: ref counted label that is equiv to merge of @a and @b 1115 + * else NULL if merge of @a and @b is not in set 1116 + */ 1117 + static struct aa_label *__label_find_merge(struct aa_labelset *ls, 1118 + struct aa_label *a, 1119 + struct aa_label *b) 1120 + { 1121 + struct rb_node *node; 1122 + 1123 + AA_BUG(!ls); 1124 + AA_BUG(!a); 1125 + AA_BUG(!b); 1126 + 1127 + if (a == b) 1128 + return __label_find(a); 1129 + 1130 + node = ls->root.rb_node; 1131 + while (node) { 1132 + struct aa_label *this = container_of(node, struct aa_label, 1133 + node); 1134 + int result = label_merge_cmp(a, b, this); 1135 + 1136 + if (result < 0) 1137 + node = node->rb_left; 1138 + else if (result > 0) 1139 + node = node->rb_right; 1140 + else 1141 + return __aa_get_label(this); 1142 + } 1143 + 1144 + return NULL; 1145 + } 1146 + 1147 + 1148 + /** 1149 + * aa_label_find_merge - find label that is equiv to merge of @a and @b 1150 + * @a: label to merge with @b (NOT NULL) 1151 + * @b: label to merge with @a (NOT NULL) 1152 + * 1153 + * Requires: labels be fully constructed with a valid ns 1154 + * 1155 + * Returns: ref counted label that is equiv to merge of @a and @b 1156 + * else NULL if merge of @a and @b is not in set 1157 + */ 1158 + struct aa_label *aa_label_find_merge(struct aa_label *a, struct aa_label *b) 1159 + { 1160 + struct aa_labelset *ls; 1161 + struct aa_label *label, *ar = NULL, *br = NULL; 1162 + unsigned long flags; 1163 + 1164 + AA_BUG(!a); 1165 + AA_BUG(!b); 1166 + 1167 + if (label_is_stale(a)) 1168 + a = ar = aa_get_newest_label(a); 1169 + if (label_is_stale(b)) 1170 + b = br = aa_get_newest_label(b); 1171 + ls = labelset_of_merge(a, b); 1172 + read_lock_irqsave(&ls->lock, flags); 1173 + label = __label_find_merge(ls, a, b); 1174 + read_unlock_irqrestore(&ls->lock, flags); 1175 + aa_put_label(ar); 1176 + aa_put_label(br); 1177 + 1178 + return label; 1179 + } 1180 + 1181 + /** 1182 + * aa_label_merge - attempt to insert new merged label of @a and @b 1183 + * @ls: set of labels to insert label into (NOT NULL) 1184 + * @a: label to merge with @b (NOT NULL) 1185 + * @b: label to merge with @a (NOT NULL) 1186 + * @gfp: memory allocation type 1187 + * 1188 + * Requires: caller to hold valid refs on @a and @b 1189 + * labels be fully constructed with a valid ns 1190 + * 1191 + * Returns: ref counted new label if successful in inserting merge of a & b 1192 + * else ref counted equivalent label that is already in the set. 1193 + * else NULL if could not create label (-ENOMEM) 1194 + */ 1195 + struct aa_label *aa_label_merge(struct aa_label *a, struct aa_label *b, 1196 + gfp_t gfp) 1197 + { 1198 + struct aa_label *label = NULL; 1199 + 1200 + AA_BUG(!a); 1201 + AA_BUG(!b); 1202 + 1203 + if (a == b) 1204 + return aa_get_newest_label(a); 1205 + 1206 + /* TODO: enable when read side is lockless 1207 + * check if label exists before taking locks 1208 + if (!label_is_stale(a) && !label_is_stale(b)) 1209 + label = aa_label_find_merge(a, b); 1210 + */ 1211 + 1212 + if (!label) { 1213 + struct aa_label *new; 1214 + 1215 + a = aa_get_newest_label(a); 1216 + b = aa_get_newest_label(b); 1217 + 1218 + /* could use label_merge_len(a, b), but requires double 1219 + * comparison for small savings 1220 + */ 1221 + new = aa_label_alloc(a->size + b->size, NULL, gfp); 1222 + if (!new) 1223 + goto out; 1224 + 1225 + label = label_merge_insert(new, a, b); 1226 + label_free_or_put_new(label, new); 1227 + out: 1228 + aa_put_label(a); 1229 + aa_put_label(b); 1230 + } 1231 + 1232 + return label; 1233 + } 1234 + 1235 + static inline bool label_is_visible(struct aa_profile *profile, 1236 + struct aa_label *label) 1237 + { 1238 + return aa_ns_visible(profile->ns, labels_ns(label), true); 1239 + } 1240 + 1241 + /* match a profile and its associated ns component if needed 1242 + * Assumes visibility test has already been done. 1243 + * If a subns profile is not to be matched should be prescreened with 1244 + * visibility test. 1245 + */ 1246 + static inline unsigned int match_component(struct aa_profile *profile, 1247 + struct aa_profile *tp, 1248 + unsigned int state) 1249 + { 1250 + const char *ns_name; 1251 + 1252 + if (profile->ns == tp->ns) 1253 + return aa_dfa_match(profile->policy.dfa, state, tp->base.hname); 1254 + 1255 + /* try matching with namespace name and then profile */ 1256 + ns_name = aa_ns_name(profile->ns, tp->ns, true); 1257 + state = aa_dfa_match_len(profile->policy.dfa, state, ":", 1); 1258 + state = aa_dfa_match(profile->policy.dfa, state, ns_name); 1259 + state = aa_dfa_match_len(profile->policy.dfa, state, ":", 1); 1260 + return aa_dfa_match(profile->policy.dfa, state, tp->base.hname); 1261 + } 1262 + 1263 + /** 1264 + * label_compound_match - find perms for full compound label 1265 + * @profile: profile to find perms for 1266 + * @label: label to check access permissions for 1267 + * @start: state to start match in 1268 + * @subns: whether to do permission checks on components in a subns 1269 + * @request: permissions to request 1270 + * @perms: perms struct to set 1271 + * 1272 + * Returns: 0 on success else ERROR 1273 + * 1274 + * For the label A//&B//&C this does the perm match for A//&B//&C 1275 + * @perms should be preinitialized with allperms OR a previous permission 1276 + * check to be stacked. 1277 + */ 1278 + static int label_compound_match(struct aa_profile *profile, 1279 + struct aa_label *label, 1280 + unsigned int state, bool subns, u32 request, 1281 + struct aa_perms *perms) 1282 + { 1283 + struct aa_profile *tp; 1284 + struct label_it i; 1285 + 1286 + /* find first subcomponent that is visible */ 1287 + label_for_each(i, label, tp) { 1288 + if (!aa_ns_visible(profile->ns, tp->ns, subns)) 1289 + continue; 1290 + state = match_component(profile, tp, state); 1291 + if (!state) 1292 + goto fail; 1293 + goto next; 1294 + } 1295 + 1296 + /* no component visible */ 1297 + *perms = allperms; 1298 + return 0; 1299 + 1300 + next: 1301 + label_for_each_cont(i, label, tp) { 1302 + if (!aa_ns_visible(profile->ns, tp->ns, subns)) 1303 + continue; 1304 + state = aa_dfa_match(profile->policy.dfa, state, "//&"); 1305 + state = match_component(profile, tp, state); 1306 + if (!state) 1307 + goto fail; 1308 + } 1309 + aa_compute_perms(profile->policy.dfa, state, perms); 1310 + aa_apply_modes_to_perms(profile, perms); 1311 + if ((perms->allow & request) != request) 1312 + return -EACCES; 1313 + 1314 + return 0; 1315 + 1316 + fail: 1317 + *perms = nullperms; 1318 + return state; 1319 + } 1320 + 1321 + /** 1322 + * label_components_match - find perms for all subcomponents of a label 1323 + * @profile: profile to find perms for 1324 + * @label: label to check access permissions for 1325 + * @start: state to start match in 1326 + * @subns: whether to do permission checks on components in a subns 1327 + * @request: permissions to request 1328 + * @perms: an initialized perms struct to add accumulation to 1329 + * 1330 + * Returns: 0 on success else ERROR 1331 + * 1332 + * For the label A//&B//&C this does the perm match for each of A and B and C 1333 + * @perms should be preinitialized with allperms OR a previous permission 1334 + * check to be stacked. 1335 + */ 1336 + static int label_components_match(struct aa_profile *profile, 1337 + struct aa_label *label, unsigned int start, 1338 + bool subns, u32 request, 1339 + struct aa_perms *perms) 1340 + { 1341 + struct aa_profile *tp; 1342 + struct label_it i; 1343 + struct aa_perms tmp; 1344 + unsigned int state = 0; 1345 + 1346 + /* find first subcomponent to test */ 1347 + label_for_each(i, label, tp) { 1348 + if (!aa_ns_visible(profile->ns, tp->ns, subns)) 1349 + continue; 1350 + state = match_component(profile, tp, start); 1351 + if (!state) 1352 + goto fail; 1353 + goto next; 1354 + } 1355 + 1356 + /* no subcomponents visible - no change in perms */ 1357 + return 0; 1358 + 1359 + next: 1360 + aa_compute_perms(profile->policy.dfa, state, &tmp); 1361 + aa_apply_modes_to_perms(profile, &tmp); 1362 + aa_perms_accum(perms, &tmp); 1363 + label_for_each_cont(i, label, tp) { 1364 + if (!aa_ns_visible(profile->ns, tp->ns, subns)) 1365 + continue; 1366 + state = match_component(profile, tp, start); 1367 + if (!state) 1368 + goto fail; 1369 + aa_compute_perms(profile->policy.dfa, state, &tmp); 1370 + aa_apply_modes_to_perms(profile, &tmp); 1371 + aa_perms_accum(perms, &tmp); 1372 + } 1373 + 1374 + if ((perms->allow & request) != request) 1375 + return -EACCES; 1376 + 1377 + return 0; 1378 + 1379 + fail: 1380 + *perms = nullperms; 1381 + return -EACCES; 1382 + } 1383 + 1384 + /** 1385 + * aa_label_match - do a multi-component label match 1386 + * @profile: profile to match against (NOT NULL) 1387 + * @label: label to match (NOT NULL) 1388 + * @state: state to start in 1389 + * @subns: whether to match subns components 1390 + * @request: permission request 1391 + * @perms: Returns computed perms (NOT NULL) 1392 + * 1393 + * Returns: the state the match finished in, may be the none matching state 1394 + */ 1395 + int aa_label_match(struct aa_profile *profile, struct aa_label *label, 1396 + unsigned int state, bool subns, u32 request, 1397 + struct aa_perms *perms) 1398 + { 1399 + int error = label_compound_match(profile, label, state, subns, request, 1400 + perms); 1401 + if (!error) 1402 + return error; 1403 + 1404 + *perms = allperms; 1405 + return label_components_match(profile, label, state, subns, request, 1406 + perms); 1407 + } 1408 + 1409 + 1410 + /** 1411 + * aa_update_label_name - update a label to have a stored name 1412 + * @ns: ns being viewed from (NOT NULL) 1413 + * @label: label to update (NOT NULL) 1414 + * @gfp: type of memory allocation 1415 + * 1416 + * Requires: labels_set(label) not locked in caller 1417 + * 1418 + * note: only updates the label name if it does not have a name already 1419 + * and if it is in the labelset 1420 + */ 1421 + bool aa_update_label_name(struct aa_ns *ns, struct aa_label *label, gfp_t gfp) 1422 + { 1423 + struct aa_labelset *ls; 1424 + unsigned long flags; 1425 + char __counted *name; 1426 + bool res = false; 1427 + 1428 + AA_BUG(!ns); 1429 + AA_BUG(!label); 1430 + 1431 + if (label->hname || labels_ns(label) != ns) 1432 + return res; 1433 + 1434 + if (aa_label_acntsxprint(&name, ns, label, FLAGS_NONE, gfp) == -1) 1435 + return res; 1436 + 1437 + ls = labels_set(label); 1438 + write_lock_irqsave(&ls->lock, flags); 1439 + if (!label->hname && label->flags & FLAG_IN_TREE) { 1440 + label->hname = name; 1441 + res = true; 1442 + } else 1443 + aa_put_str(name); 1444 + write_unlock_irqrestore(&ls->lock, flags); 1445 + 1446 + return res; 1447 + } 1448 + 1449 + /* 1450 + * cached label name is present and visible 1451 + * @label->hname only exists if label is namespace hierachical 1452 + */ 1453 + static inline bool use_label_hname(struct aa_ns *ns, struct aa_label *label) 1454 + { 1455 + if (label->hname && labels_ns(label) == ns) 1456 + return true; 1457 + 1458 + return false; 1459 + } 1460 + 1461 + /* helper macro for snprint routines */ 1462 + #define update_for_len(total, len, size, str) \ 1463 + do { \ 1464 + AA_BUG(len < 0); \ 1465 + total += len; \ 1466 + len = min(len, size); \ 1467 + size -= len; \ 1468 + str += len; \ 1469 + } while (0) 1470 + 1471 + /** 1472 + * aa_profile_snxprint - print a profile name to a buffer 1473 + * @str: buffer to write to. (MAY BE NULL if @size == 0) 1474 + * @size: size of buffer 1475 + * @view: namespace profile is being viewed from 1476 + * @profile: profile to view (NOT NULL) 1477 + * @flags: whether to include the mode string 1478 + * @prev_ns: last ns printed when used in compound print 1479 + * 1480 + * Returns: size of name written or would be written if larger than 1481 + * available buffer 1482 + * 1483 + * Note: will not print anything if the profile is not visible 1484 + */ 1485 + static int aa_profile_snxprint(char *str, size_t size, struct aa_ns *view, 1486 + struct aa_profile *profile, int flags, 1487 + struct aa_ns **prev_ns) 1488 + { 1489 + const char *ns_name = NULL; 1490 + 1491 + AA_BUG(!str && size != 0); 1492 + AA_BUG(!profile); 1493 + 1494 + if (!view) 1495 + view = profiles_ns(profile); 1496 + 1497 + if (view != profile->ns && 1498 + (!prev_ns || (prev_ns && *prev_ns != profile->ns))) { 1499 + if (prev_ns) 1500 + *prev_ns = profile->ns; 1501 + ns_name = aa_ns_name(view, profile->ns, 1502 + flags & FLAG_VIEW_SUBNS); 1503 + if (ns_name == aa_hidden_ns_name) { 1504 + if (flags & FLAG_HIDDEN_UNCONFINED) 1505 + return snprintf(str, size, "%s", "unconfined"); 1506 + return snprintf(str, size, "%s", ns_name); 1507 + } 1508 + } 1509 + 1510 + if ((flags & FLAG_SHOW_MODE) && profile != profile->ns->unconfined) { 1511 + const char *modestr = aa_profile_mode_names[profile->mode]; 1512 + 1513 + if (ns_name) 1514 + return snprintf(str, size, ":%s:%s (%s)", ns_name, 1515 + profile->base.hname, modestr); 1516 + return snprintf(str, size, "%s (%s)", profile->base.hname, 1517 + modestr); 1518 + } 1519 + 1520 + if (ns_name) 1521 + return snprintf(str, size, ":%s:%s", ns_name, 1522 + profile->base.hname); 1523 + return snprintf(str, size, "%s", profile->base.hname); 1524 + } 1525 + 1526 + static const char *label_modename(struct aa_ns *ns, struct aa_label *label, 1527 + int flags) 1528 + { 1529 + struct aa_profile *profile; 1530 + struct label_it i; 1531 + int mode = -1, count = 0; 1532 + 1533 + label_for_each(i, label, profile) { 1534 + if (aa_ns_visible(ns, profile->ns, flags & FLAG_VIEW_SUBNS)) { 1535 + if (profile->mode == APPARMOR_UNCONFINED) 1536 + /* special case unconfined so stacks with 1537 + * unconfined don't report as mixed. ie. 1538 + * profile_foo//&:ns1:unconfined (mixed) 1539 + */ 1540 + continue; 1541 + count++; 1542 + if (mode == -1) 1543 + mode = profile->mode; 1544 + else if (mode != profile->mode) 1545 + return "mixed"; 1546 + } 1547 + } 1548 + 1549 + if (count == 0) 1550 + return "-"; 1551 + if (mode == -1) 1552 + /* everything was unconfined */ 1553 + mode = APPARMOR_UNCONFINED; 1554 + 1555 + return aa_profile_mode_names[mode]; 1556 + } 1557 + 1558 + /* if any visible label is not unconfined the display_mode returns true */ 1559 + static inline bool display_mode(struct aa_ns *ns, struct aa_label *label, 1560 + int flags) 1561 + { 1562 + if ((flags & FLAG_SHOW_MODE)) { 1563 + struct aa_profile *profile; 1564 + struct label_it i; 1565 + 1566 + label_for_each(i, label, profile) { 1567 + if (aa_ns_visible(ns, profile->ns, 1568 + flags & FLAG_VIEW_SUBNS) && 1569 + profile != profile->ns->unconfined) 1570 + return true; 1571 + } 1572 + /* only ns->unconfined in set of profiles in ns */ 1573 + return false; 1574 + } 1575 + 1576 + return false; 1577 + } 1578 + 1579 + /** 1580 + * aa_label_snxprint - print a label name to a string buffer 1581 + * @str: buffer to write to. (MAY BE NULL if @size == 0) 1582 + * @size: size of buffer 1583 + * @ns: namespace profile is being viewed from 1584 + * @label: label to view (NOT NULL) 1585 + * @flags: whether to include the mode string 1586 + * 1587 + * Returns: size of name written or would be written if larger than 1588 + * available buffer 1589 + * 1590 + * Note: labels do not have to be strictly hierarchical to the ns as 1591 + * objects may be shared across different namespaces and thus 1592 + * pickup labeling from each ns. If a particular part of the 1593 + * label is not visible it will just be excluded. And if none 1594 + * of the label is visible "---" will be used. 1595 + */ 1596 + int aa_label_snxprint(char *str, size_t size, struct aa_ns *ns, 1597 + struct aa_label *label, int flags) 1598 + { 1599 + struct aa_profile *profile; 1600 + struct aa_ns *prev_ns = NULL; 1601 + struct label_it i; 1602 + int count = 0, total = 0; 1603 + size_t len; 1604 + 1605 + AA_BUG(!str && size != 0); 1606 + AA_BUG(!label); 1607 + 1608 + if (!ns) 1609 + ns = labels_ns(label); 1610 + 1611 + label_for_each(i, label, profile) { 1612 + if (aa_ns_visible(ns, profile->ns, flags & FLAG_VIEW_SUBNS)) { 1613 + if (count > 0) { 1614 + len = snprintf(str, size, "//&"); 1615 + update_for_len(total, len, size, str); 1616 + } 1617 + len = aa_profile_snxprint(str, size, ns, profile, 1618 + flags & FLAG_VIEW_SUBNS, 1619 + &prev_ns); 1620 + update_for_len(total, len, size, str); 1621 + count++; 1622 + } 1623 + } 1624 + 1625 + if (count == 0) { 1626 + if (flags & FLAG_HIDDEN_UNCONFINED) 1627 + return snprintf(str, size, "%s", "unconfined"); 1628 + return snprintf(str, size, "%s", aa_hidden_ns_name); 1629 + } 1630 + 1631 + /* count == 1 && ... is for backwards compat where the mode 1632 + * is not displayed for 'unconfined' in the current ns 1633 + */ 1634 + if (display_mode(ns, label, flags)) { 1635 + len = snprintf(str, size, " (%s)", 1636 + label_modename(ns, label, flags)); 1637 + update_for_len(total, len, size, str); 1638 + } 1639 + 1640 + return total; 1641 + } 1642 + #undef update_for_len 1643 + 1644 + /** 1645 + * aa_label_asxprint - allocate a string buffer and print label into it 1646 + * @strp: Returns - the allocated buffer with the label name. (NOT NULL) 1647 + * @ns: namespace profile is being viewed from 1648 + * @label: label to view (NOT NULL) 1649 + * @flags: flags controlling what label info is printed 1650 + * @gfp: kernel memory allocation type 1651 + * 1652 + * Returns: size of name written or would be written if larger than 1653 + * available buffer 1654 + */ 1655 + int aa_label_asxprint(char **strp, struct aa_ns *ns, struct aa_label *label, 1656 + int flags, gfp_t gfp) 1657 + { 1658 + int size; 1659 + 1660 + AA_BUG(!strp); 1661 + AA_BUG(!label); 1662 + 1663 + size = aa_label_snxprint(NULL, 0, ns, label, flags); 1664 + if (size < 0) 1665 + return size; 1666 + 1667 + *strp = kmalloc(size + 1, gfp); 1668 + if (!*strp) 1669 + return -ENOMEM; 1670 + return aa_label_snxprint(*strp, size + 1, ns, label, flags); 1671 + } 1672 + 1673 + /** 1674 + * aa_label_acntsxprint - allocate a __counted string buffer and print label 1675 + * @strp: buffer to write to. (MAY BE NULL if @size == 0) 1676 + * @ns: namespace profile is being viewed from 1677 + * @label: label to view (NOT NULL) 1678 + * @flags: flags controlling what label info is printed 1679 + * @gfp: kernel memory allocation type 1680 + * 1681 + * Returns: size of name written or would be written if larger than 1682 + * available buffer 1683 + */ 1684 + int aa_label_acntsxprint(char __counted **strp, struct aa_ns *ns, 1685 + struct aa_label *label, int flags, gfp_t gfp) 1686 + { 1687 + int size; 1688 + 1689 + AA_BUG(!strp); 1690 + AA_BUG(!label); 1691 + 1692 + size = aa_label_snxprint(NULL, 0, ns, label, flags); 1693 + if (size < 0) 1694 + return size; 1695 + 1696 + *strp = aa_str_alloc(size + 1, gfp); 1697 + if (!*strp) 1698 + return -ENOMEM; 1699 + return aa_label_snxprint(*strp, size + 1, ns, label, flags); 1700 + } 1701 + 1702 + 1703 + void aa_label_xaudit(struct audit_buffer *ab, struct aa_ns *ns, 1704 + struct aa_label *label, int flags, gfp_t gfp) 1705 + { 1706 + const char *str; 1707 + char *name = NULL; 1708 + int len; 1709 + 1710 + AA_BUG(!ab); 1711 + AA_BUG(!label); 1712 + 1713 + if (!ns) 1714 + ns = labels_ns(label); 1715 + 1716 + if (!use_label_hname(ns, label) || display_mode(ns, label, flags)) { 1717 + len = aa_label_asxprint(&name, ns, label, flags, gfp); 1718 + if (len == -1) { 1719 + AA_DEBUG("label print error"); 1720 + return; 1721 + } 1722 + str = name; 1723 + } else { 1724 + str = (char *) label->hname; 1725 + len = strlen(str); 1726 + } 1727 + if (audit_string_contains_control(str, len)) 1728 + audit_log_n_hex(ab, str, len); 1729 + else 1730 + audit_log_n_string(ab, str, len); 1731 + 1732 + kfree(name); 1733 + } 1734 + 1735 + void aa_label_seq_xprint(struct seq_file *f, struct aa_ns *ns, 1736 + struct aa_label *label, int flags, gfp_t gfp) 1737 + { 1738 + AA_BUG(!f); 1739 + AA_BUG(!label); 1740 + 1741 + if (!ns) 1742 + ns = labels_ns(label); 1743 + 1744 + if (!use_label_hname(ns, label)) { 1745 + char *str; 1746 + int len; 1747 + 1748 + len = aa_label_asxprint(&str, ns, label, flags, gfp); 1749 + if (len == -1) { 1750 + AA_DEBUG("label print error"); 1751 + return; 1752 + } 1753 + seq_printf(f, "%s", str); 1754 + kfree(str); 1755 + } else if (display_mode(ns, label, flags)) 1756 + seq_printf(f, "%s (%s)", label->hname, 1757 + label_modename(ns, label, flags)); 1758 + else 1759 + seq_printf(f, "%s", label->hname); 1760 + } 1761 + 1762 + void aa_label_xprintk(struct aa_ns *ns, struct aa_label *label, int flags, 1763 + gfp_t gfp) 1764 + { 1765 + AA_BUG(!label); 1766 + 1767 + if (!ns) 1768 + ns = labels_ns(label); 1769 + 1770 + if (!use_label_hname(ns, label)) { 1771 + char *str; 1772 + int len; 1773 + 1774 + len = aa_label_asxprint(&str, ns, label, flags, gfp); 1775 + if (len == -1) { 1776 + AA_DEBUG("label print error"); 1777 + return; 1778 + } 1779 + pr_info("%s", str); 1780 + kfree(str); 1781 + } else if (display_mode(ns, label, flags)) 1782 + pr_info("%s (%s)", label->hname, 1783 + label_modename(ns, label, flags)); 1784 + else 1785 + pr_info("%s", label->hname); 1786 + } 1787 + 1788 + void aa_label_audit(struct audit_buffer *ab, struct aa_label *label, gfp_t gfp) 1789 + { 1790 + struct aa_ns *ns = aa_get_current_ns(); 1791 + 1792 + aa_label_xaudit(ab, ns, label, FLAG_VIEW_SUBNS, gfp); 1793 + aa_put_ns(ns); 1794 + } 1795 + 1796 + void aa_label_seq_print(struct seq_file *f, struct aa_label *label, gfp_t gfp) 1797 + { 1798 + struct aa_ns *ns = aa_get_current_ns(); 1799 + 1800 + aa_label_seq_xprint(f, ns, label, FLAG_VIEW_SUBNS, gfp); 1801 + aa_put_ns(ns); 1802 + } 1803 + 1804 + void aa_label_printk(struct aa_label *label, gfp_t gfp) 1805 + { 1806 + struct aa_ns *ns = aa_get_current_ns(); 1807 + 1808 + aa_label_xprintk(ns, label, FLAG_VIEW_SUBNS, gfp); 1809 + aa_put_ns(ns); 1810 + } 1811 + 1812 + static int label_count_str_entries(const char *str) 1813 + { 1814 + const char *split; 1815 + int count = 1; 1816 + 1817 + AA_BUG(!str); 1818 + 1819 + for (split = strstr(str, "//&"); split; split = strstr(str, "//&")) { 1820 + count++; 1821 + str = split + 3; 1822 + } 1823 + 1824 + return count; 1825 + } 1826 + 1827 + /* 1828 + * ensure stacks with components like 1829 + * :ns:A//&B 1830 + * have :ns: applied to both 'A' and 'B' by making the lookup relative 1831 + * to the base if the lookup specifies an ns, else making the stacked lookup 1832 + * relative to the last embedded ns in the string. 1833 + */ 1834 + static struct aa_profile *fqlookupn_profile(struct aa_label *base, 1835 + struct aa_label *currentbase, 1836 + const char *str, size_t n) 1837 + { 1838 + const char *first = skipn_spaces(str, n); 1839 + 1840 + if (first && *first == ':') 1841 + return aa_fqlookupn_profile(base, str, n); 1842 + 1843 + return aa_fqlookupn_profile(currentbase, str, n); 1844 + } 1845 + 1846 + /** 1847 + * aa_label_parse - parse, validate and convert a text string to a label 1848 + * @base: base label to use for lookups (NOT NULL) 1849 + * @str: null terminated text string (NOT NULL) 1850 + * @gfp: allocation type 1851 + * @create: true if should create compound labels if they don't exist 1852 + * @force_stack: true if should stack even if no leading & 1853 + * 1854 + * Returns: the matching refcounted label if present 1855 + * else ERRPTR 1856 + */ 1857 + struct aa_label *aa_label_parse(struct aa_label *base, const char *str, 1858 + gfp_t gfp, bool create, bool force_stack) 1859 + { 1860 + DEFINE_VEC(profile, vec); 1861 + struct aa_label *label, *currbase = base; 1862 + int i, len, stack = 0, error; 1863 + char *split; 1864 + 1865 + AA_BUG(!base); 1866 + AA_BUG(!str); 1867 + 1868 + str = skip_spaces(str); 1869 + len = label_count_str_entries(str); 1870 + if (*str == '&' || force_stack) { 1871 + /* stack on top of base */ 1872 + stack = base->size; 1873 + len += stack; 1874 + if (*str == '&') 1875 + str++; 1876 + } 1877 + error = vec_setup(profile, vec, len, gfp); 1878 + if (error) 1879 + return ERR_PTR(error); 1880 + 1881 + for (i = 0; i < stack; i++) 1882 + vec[i] = aa_get_profile(base->vec[i]); 1883 + 1884 + for (split = strstr(str, "//&"), i = stack; split && i < len; i++) { 1885 + vec[i] = fqlookupn_profile(base, currbase, str, split - str); 1886 + if (!vec[i]) 1887 + goto fail; 1888 + /* 1889 + * if component specified a new ns it becomes the new base 1890 + * so that subsequent lookups are relative to it 1891 + */ 1892 + if (vec[i]->ns != labels_ns(currbase)) 1893 + currbase = &vec[i]->label; 1894 + str = split + 3; 1895 + split = strstr(str, "//&"); 1896 + } 1897 + /* last element doesn't have a split */ 1898 + if (i < len) { 1899 + vec[i] = fqlookupn_profile(base, currbase, str, strlen(str)); 1900 + if (!vec[i]) 1901 + goto fail; 1902 + } 1903 + if (len == 1) 1904 + /* no need to free vec as len < LOCAL_VEC_ENTRIES */ 1905 + return &vec[0]->label; 1906 + 1907 + len -= aa_vec_unique(vec, len, VEC_FLAG_TERMINATE); 1908 + /* TODO: deal with reference labels */ 1909 + if (len == 1) { 1910 + label = aa_get_label(&vec[0]->label); 1911 + goto out; 1912 + } 1913 + 1914 + if (create) 1915 + label = aa_vec_find_or_create_label(vec, len, gfp); 1916 + else 1917 + label = vec_find(vec, len); 1918 + if (!label) 1919 + goto fail; 1920 + 1921 + out: 1922 + /* use adjusted len from after vec_unique, not original */ 1923 + vec_cleanup(profile, vec, len); 1924 + return label; 1925 + 1926 + fail: 1927 + label = ERR_PTR(-ENOENT); 1928 + goto out; 1929 + } 1930 + 1931 + 1932 + /** 1933 + * aa_labelset_destroy - remove all labels from the label set 1934 + * @ls: label set to cleanup (NOT NULL) 1935 + * 1936 + * Labels that are removed from the set may still exist beyond the set 1937 + * being destroyed depending on their reference counting 1938 + */ 1939 + void aa_labelset_destroy(struct aa_labelset *ls) 1940 + { 1941 + struct rb_node *node; 1942 + unsigned long flags; 1943 + 1944 + AA_BUG(!ls); 1945 + 1946 + write_lock_irqsave(&ls->lock, flags); 1947 + for (node = rb_first(&ls->root); node; node = rb_first(&ls->root)) { 1948 + struct aa_label *this = rb_entry(node, struct aa_label, node); 1949 + 1950 + if (labels_ns(this) != root_ns) 1951 + __label_remove(this, 1952 + ns_unconfined(labels_ns(this)->parent)); 1953 + else 1954 + __label_remove(this, NULL); 1955 + } 1956 + write_unlock_irqrestore(&ls->lock, flags); 1957 + } 1958 + 1959 + /* 1960 + * @ls: labelset to init (NOT NULL) 1961 + */ 1962 + void aa_labelset_init(struct aa_labelset *ls) 1963 + { 1964 + AA_BUG(!ls); 1965 + 1966 + rwlock_init(&ls->lock); 1967 + ls->root = RB_ROOT; 1968 + } 1969 + 1970 + static struct aa_label *labelset_next_stale(struct aa_labelset *ls) 1971 + { 1972 + struct aa_label *label; 1973 + struct rb_node *node; 1974 + unsigned long flags; 1975 + 1976 + AA_BUG(!ls); 1977 + 1978 + read_lock_irqsave(&ls->lock, flags); 1979 + 1980 + __labelset_for_each(ls, node) { 1981 + label = rb_entry(node, struct aa_label, node); 1982 + if ((label_is_stale(label) || 1983 + vec_is_stale(label->vec, label->size)) && 1984 + __aa_get_label(label)) 1985 + goto out; 1986 + 1987 + } 1988 + label = NULL; 1989 + 1990 + out: 1991 + read_unlock_irqrestore(&ls->lock, flags); 1992 + 1993 + return label; 1994 + } 1995 + 1996 + /** 1997 + * __label_update - insert updated version of @label into labelset 1998 + * @label - the label to update/repace 1999 + * 2000 + * Returns: new label that is up to date 2001 + * else NULL on failure 2002 + * 2003 + * Requires: @ns lock be held 2004 + * 2005 + * Note: worst case is the stale @label does not get updated and has 2006 + * to be updated at a later time. 2007 + */ 2008 + static struct aa_label *__label_update(struct aa_label *label) 2009 + { 2010 + struct aa_label *new, *tmp; 2011 + struct aa_labelset *ls; 2012 + unsigned long flags; 2013 + int i, invcount = 0; 2014 + 2015 + AA_BUG(!label); 2016 + AA_BUG(!mutex_is_locked(&labels_ns(label)->lock)); 2017 + 2018 + new = aa_label_alloc(label->size, label->proxy, GFP_KERNEL); 2019 + if (!new) 2020 + return NULL; 2021 + 2022 + /* 2023 + * while holding the ns_lock will stop profile replacement, removal, 2024 + * and label updates, label merging and removal can be occurring 2025 + */ 2026 + ls = labels_set(label); 2027 + write_lock_irqsave(&ls->lock, flags); 2028 + for (i = 0; i < label->size; i++) { 2029 + AA_BUG(!label->vec[i]); 2030 + new->vec[i] = aa_get_newest_profile(label->vec[i]); 2031 + AA_BUG(!new->vec[i]); 2032 + AA_BUG(!new->vec[i]->label.proxy); 2033 + AA_BUG(!new->vec[i]->label.proxy->label); 2034 + if (new->vec[i]->label.proxy != label->vec[i]->label.proxy) 2035 + invcount++; 2036 + } 2037 + 2038 + /* updated stale label by being removed/renamed from labelset */ 2039 + if (invcount) { 2040 + new->size -= aa_vec_unique(&new->vec[0], new->size, 2041 + VEC_FLAG_TERMINATE); 2042 + /* TODO: deal with reference labels */ 2043 + if (new->size == 1) { 2044 + tmp = aa_get_label(&new->vec[0]->label); 2045 + AA_BUG(tmp == label); 2046 + goto remove; 2047 + } 2048 + if (labels_set(label) != labels_set(new)) { 2049 + write_unlock_irqrestore(&ls->lock, flags); 2050 + tmp = aa_label_insert(labels_set(new), new); 2051 + write_lock_irqsave(&ls->lock, flags); 2052 + goto remove; 2053 + } 2054 + } else 2055 + AA_BUG(labels_ns(label) != labels_ns(new)); 2056 + 2057 + tmp = __label_insert(labels_set(label), new, true); 2058 + remove: 2059 + /* ensure label is removed, and redirected correctly */ 2060 + __label_remove(label, tmp); 2061 + write_unlock_irqrestore(&ls->lock, flags); 2062 + label_free_or_put_new(tmp, new); 2063 + 2064 + return tmp; 2065 + } 2066 + 2067 + /** 2068 + * __labelset_update - update labels in @ns 2069 + * @ns: namespace to update labels in (NOT NULL) 2070 + * 2071 + * Requires: @ns lock be held 2072 + * 2073 + * Walk the labelset ensuring that all labels are up to date and valid 2074 + * Any label that has a stale component is marked stale and replaced and 2075 + * by an updated version. 2076 + * 2077 + * If failures happen due to memory pressures then stale labels will 2078 + * be left in place until the next pass. 2079 + */ 2080 + static void __labelset_update(struct aa_ns *ns) 2081 + { 2082 + struct aa_label *label; 2083 + 2084 + AA_BUG(!ns); 2085 + AA_BUG(!mutex_is_locked(&ns->lock)); 2086 + 2087 + do { 2088 + label = labelset_next_stale(&ns->labels); 2089 + if (label) { 2090 + struct aa_label *l = __label_update(label); 2091 + 2092 + aa_put_label(l); 2093 + aa_put_label(label); 2094 + } 2095 + } while (label); 2096 + } 2097 + 2098 + /** 2099 + * __aa_labelset_udate_subtree - update all labels with a stale component 2100 + * @ns: ns to start update at (NOT NULL) 2101 + * 2102 + * Requires: @ns lock be held 2103 + * 2104 + * Invalidates labels based on @p in @ns and any children namespaces. 2105 + */ 2106 + void __aa_labelset_update_subtree(struct aa_ns *ns) 2107 + { 2108 + struct aa_ns *child; 2109 + 2110 + AA_BUG(!ns); 2111 + AA_BUG(!mutex_is_locked(&ns->lock)); 2112 + 2113 + __labelset_update(ns); 2114 + 2115 + list_for_each_entry(child, &ns->sub_ns, base.list) { 2116 + mutex_lock(&child->lock); 2117 + __aa_labelset_update_subtree(child); 2118 + mutex_unlock(&child->lock); 2119 + } 2120 + }