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

Configure Feed

Select the types of activity you want to include in your feed.

apparmor: carry mediation check on label

In order to speed up the mediated check, precompute and store the
result as a bit per class type. This will not only allow us to
speed up the mediation check but is also a step to removing the
unconfined special cases as the unconfined check can be replaced
with the generic label_mediates() check.

Note: label check does not currently work for capabilities and resources
which need to have their mediation updated first.

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

+68 -24
+1
security/apparmor/include/apparmor.h
··· 38 38 #define AA_CLASS_X 31 39 39 #define AA_CLASS_DBUS 32 40 40 41 + /* NOTE: if AA_CLASS_LAST > 63 need to update label->mediates */ 41 42 #define AA_CLASS_LAST AA_CLASS_DBUS 42 43 43 44 /* Control parameters settable through module/boot flags */
+11 -13
security/apparmor/include/label.h
··· 129 129 long flags; 130 130 u32 secid; 131 131 int size; 132 + u64 mediates; 132 133 struct aa_profile *vec[]; 133 134 }; 134 135 ··· 232 231 #define fn_for_each_not_in_set(L1, L2, P, FN) \ 233 232 fn_for_each2_XXX((L1), (L2), P, FN, _not_in_set) 234 233 235 - #define LABEL_MEDIATES(L, C) \ 236 - ({ \ 237 - struct aa_profile *profile; \ 238 - struct label_it i; \ 239 - int ret = 0; \ 240 - label_for_each(i, (L), profile) { \ 241 - if (RULE_MEDIATES(&profile->rules, (C))) { \ 242 - ret = 1; \ 243 - break; \ 244 - } \ 245 - } \ 246 - ret; \ 247 - }) 234 + static inline bool label_mediates(struct aa_label *L, unsigned char C) 235 + { 236 + return (L)->mediates & (((u64) 1) << (C)); 237 + } 248 238 239 + static inline bool label_mediates_safe(struct aa_label *L, unsigned char C) 240 + { 241 + if (C > AA_CLASS_LAST) 242 + return false; 243 + return label_mediates(L, C); 244 + } 249 245 250 246 void aa_labelset_destroy(struct aa_labelset *ls); 251 247 void aa_labelset_init(struct aa_labelset *ls);
+13
security/apparmor/include/policy.h
··· 318 318 return RULE_MEDIATES(rule, class); 319 319 } 320 320 321 + void aa_compute_profile_mediates(struct aa_profile *profile); 322 + static inline bool profile_mediates(struct aa_profile *profile, 323 + unsigned char class) 324 + { 325 + return label_mediates(&profile->label, class); 326 + } 327 + 328 + static inline bool profile_mediates_safe(struct aa_profile *profile, 329 + unsigned char class) 330 + { 331 + return label_mediates_safe(&profile->label, class); 332 + } 333 + 321 334 /** 322 335 * aa_get_profile - increment refcount on profile @p 323 336 * @p: profile (MAYBE NULL)
+14 -10
security/apparmor/label.c
··· 198 198 return false; 199 199 } 200 200 201 - static long accum_vec_flags(struct aa_profile **vec, int n) 201 + static void accum_label_info(struct aa_label *new) 202 202 { 203 203 long u = FLAG_UNCONFINED; 204 204 int i; 205 205 206 - AA_BUG(!vec); 206 + AA_BUG(!new->vec); 207 207 208 - for (i = 0; i < n; i++) { 209 - u |= vec[i]->label.flags & (FLAG_DEBUG1 | FLAG_DEBUG2 | 210 - FLAG_STALE); 211 - if (!(u & vec[i]->label.flags & FLAG_UNCONFINED)) 208 + /* size == 1 is a profile and flags must be set as part of creation */ 209 + if (new->size == 1) 210 + return; 211 + 212 + for (i = 0; i < new->size; i++) { 213 + u |= new->vec[i]->label.flags & (FLAG_DEBUG1 | FLAG_DEBUG2 | 214 + FLAG_STALE); 215 + if (!(u & new->vec[i]->label.flags & FLAG_UNCONFINED)) 212 216 u &= ~FLAG_UNCONFINED; 217 + new->mediates |= new->vec[i]->label.mediates; 213 218 } 214 - 215 - return u; 219 + new->flags |= u; 216 220 } 217 221 218 222 static int sort_cmp(const void *a, const void *b) ··· 649 645 rb_replace_node(&old->node, &new->node, &ls->root); 650 646 old->flags &= ~FLAG_IN_TREE; 651 647 new->flags |= FLAG_IN_TREE; 652 - new->flags |= accum_vec_flags(new->vec, new->size); 648 + accum_label_info(new); 653 649 return true; 654 650 } 655 651 ··· 710 706 rb_link_node(&label->node, parent, new); 711 707 rb_insert_color(&label->node, &ls->root); 712 708 label->flags |= FLAG_IN_TREE; 713 - label->flags |= accum_vec_flags(label->vec, label->size); 709 + accum_label_info(label); 714 710 715 711 return aa_get_label(label); 716 712 }
+27 -1
security/apparmor/policy.c
··· 373 373 return NULL; 374 374 } 375 375 376 + /* set of rules that are mediated by unconfined */ 377 + static int unconfined_mediates[] = { AA_CLASS_NS, AA_CLASS_IO_URING, 0 }; 378 + 379 + /* must be called after profile rulesets and start information is setup */ 380 + void aa_compute_profile_mediates(struct aa_profile *profile) 381 + { 382 + int c; 383 + 384 + if (profile_unconfined(profile)) { 385 + int *pos; 386 + 387 + for (pos = unconfined_mediates; *pos; pos++) { 388 + if (ANY_RULE_MEDIATES(&profile->rules, AA_CLASS_NS) != 389 + DFA_NOMATCH) 390 + profile->label.mediates |= ((u64) 1) << AA_CLASS_NS; 391 + } 392 + return; 393 + } 394 + for (c = 0; c <= AA_CLASS_LAST; c++) { 395 + if (ANY_RULE_MEDIATES(&profile->rules, c) != DFA_NOMATCH) 396 + profile->label.mediates |= ((u64) 1) << c; 397 + } 398 + } 399 + 376 400 /* TODO: profile accounting - setup in remove */ 377 401 378 402 /** ··· 648 624 rules = list_first_entry(&profile->rules, typeof(*rules), list); 649 625 rules->file = aa_get_pdb(nullpdb); 650 626 rules->policy = aa_get_pdb(nullpdb); 627 + aa_compute_profile_mediates(profile); 651 628 652 629 if (parent) { 653 630 profile->path_flags = parent->path_flags; 654 - 631 + /* override/inherit what is mediated from parent */ 632 + profile->label.mediates = parent->label.mediates; 655 633 /* released on free_profile */ 656 634 rcu_assign_pointer(profile->parent, aa_get_profile(parent)); 657 635 profile->ns = aa_get_ns(parent->ns);
+2
security/apparmor/policy_unpack.c
··· 1101 1101 goto fail; 1102 1102 } 1103 1103 1104 + aa_compute_profile_mediates(profile); 1105 + 1104 1106 return profile; 1105 1107 1106 1108 fail: