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: transition from a list of rules to a vector of rules

The set of rules on a profile is not dynamically extended, instead
if a new ruleset is needed a new version of the profile is created.
This allows us to use a vector of rules instead of a list, slightly
reducing memory usage and simplifying the code.

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

+85 -113
+7 -15
security/apparmor/af_unix.c
··· 202 202 int type, int protocol, 203 203 struct apparmor_audit_data *ad) 204 204 { 205 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 206 - typeof(*rules), list); 205 + struct aa_ruleset *rules = profile->label.rules[0]; 207 206 aa_state_t state; 208 207 209 208 AA_BUG(!profile); ··· 226 227 struct apparmor_audit_data *ad, 227 228 u32 request, struct sock *sk, struct path *path) 228 229 { 229 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 230 - typeof(*rules), 231 - list); 230 + struct aa_ruleset *rules = profile->label.rules[0]; 232 231 struct aa_perms *p = NULL; 233 232 aa_state_t state; 234 233 ··· 254 257 static int profile_bind_perm(struct aa_profile *profile, struct sock *sk, 255 258 struct apparmor_audit_data *ad) 256 259 { 257 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 258 - typeof(*rules), list); 260 + struct aa_ruleset *rules = profile->label.rules[0]; 259 261 struct aa_perms *p = NULL; 260 262 aa_state_t state; 261 263 ··· 285 289 static int profile_listen_perm(struct aa_profile *profile, struct sock *sk, 286 290 int backlog, struct apparmor_audit_data *ad) 287 291 { 288 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 289 - typeof(*rules), list); 292 + struct aa_ruleset *rules = profile->label.rules[0]; 290 293 struct aa_perms *p = NULL; 291 294 aa_state_t state; 292 295 ··· 322 327 struct sock *sk, 323 328 struct apparmor_audit_data *ad) 324 329 { 325 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 326 - typeof(*rules), list); 330 + struct aa_ruleset *rules = profile->label.rules[0]; 327 331 struct aa_perms *p = NULL; 328 332 aa_state_t state; 329 333 ··· 352 358 struct sock *sk, int optname, 353 359 struct apparmor_audit_data *ad) 354 360 { 355 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 356 - typeof(*rules), list); 361 + struct aa_ruleset *rules = profile->label.rules[0]; 357 362 struct aa_perms *p = NULL; 358 363 aa_state_t state; 359 364 ··· 392 399 struct aa_label *peer_label, 393 400 struct apparmor_audit_data *ad) 394 401 { 395 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 396 - typeof(*rules), list); 402 + struct aa_ruleset *rules = profile->label.rules[0]; 397 403 struct aa_perms *p = NULL; 398 404 aa_state_t state; 399 405
+1 -2
security/apparmor/apparmorfs.c
··· 612 612 static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms, 613 613 const char *match_str, size_t match_len) 614 614 { 615 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 616 - typeof(*rules), list); 615 + struct aa_ruleset *rules = profile->label.rules[0]; 617 616 struct aa_perms tmp = { }; 618 617 aa_state_t state = DFA_NOMATCH; 619 618
+3 -6
security/apparmor/capability.c
··· 69 69 { 70 70 const u64 AUDIT_CACHE_TIMEOUT_NS = 1000*1000*1000; /* 1 second */ 71 71 72 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 73 - typeof(*rules), list); 72 + struct aa_ruleset *rules = profile->label.rules[0]; 74 73 struct audit_cache *ent; 75 74 int type = AUDIT_APPARMOR_AUTO; 76 75 ··· 121 122 static int profile_capable(struct aa_profile *profile, int cap, 122 123 unsigned int opts, struct apparmor_audit_data *ad) 123 124 { 124 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 125 - typeof(*rules), list); 125 + struct aa_ruleset *rules = profile->label.rules[0]; 126 126 aa_state_t state; 127 127 int error; 128 128 ··· 193 195 194 196 kernel_cap_t aa_profile_capget(struct aa_profile *profile) 195 197 { 196 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 197 - typeof(*rules), list); 198 + struct aa_ruleset *rules = profile->label.rules[0]; 198 199 aa_state_t state; 199 200 200 201 state = RULE_MEDIATES(rules, AA_CLASS_CAP);
+7 -16
security/apparmor/domain.c
··· 93 93 struct aa_profile *tp, 94 94 bool stack, aa_state_t state) 95 95 { 96 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 97 - typeof(*rules), list); 96 + struct aa_ruleset *rules = profile->label.rules[0]; 98 97 const char *ns_name; 99 98 100 99 if (stack) ··· 130 131 aa_state_t state, bool subns, u32 request, 131 132 struct aa_perms *perms) 132 133 { 133 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 134 - typeof(*rules), list); 134 + struct aa_ruleset *rules = profile->label.rules[0]; 135 135 struct aa_profile *tp; 136 136 struct label_it i; 137 137 struct path_cond cond = { }; ··· 192 194 aa_state_t start, bool subns, u32 request, 193 195 struct aa_perms *perms) 194 196 { 195 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 196 - typeof(*rules), list); 197 + struct aa_ruleset *rules = profile->label.rules[0]; 197 198 struct aa_profile *tp; 198 199 struct label_it i; 199 200 struct aa_perms tmp; ··· 517 520 struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, 518 521 const char **name) 519 522 { 520 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 521 - typeof(*rules), list); 523 + struct aa_ruleset *rules = profile->label.rules[0]; 522 524 struct aa_label *label = NULL; 523 525 u32 xtype = xindex & AA_X_TYPE_MASK; 524 526 int index = xindex & AA_X_INDEX_MASK; ··· 571 575 const char **lookupname, 572 576 const char **info) 573 577 { 574 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 575 - typeof(*rules), list); 576 578 struct aa_label *new = NULL; 577 579 struct aa_label *stack = NULL; 578 580 struct aa_ns *ns = profile->ns; ··· 662 668 char *buffer, struct path_cond *cond, 663 669 bool *secure_exec) 664 670 { 665 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 666 - typeof(*rules), list); 671 + struct aa_ruleset *rules = profile->label.rules[0]; 667 672 struct aa_label *new = NULL; 668 673 struct aa_profile *new_profile = NULL; 669 674 const char *info = NULL, *name = NULL, *target = NULL; ··· 795 802 char *buffer, struct path_cond *cond, 796 803 bool *secure_exec) 797 804 { 798 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 799 - typeof(*rules), list); 805 + struct aa_ruleset *rules = profile->label.rules[0]; 800 806 aa_state_t state = rules->file->start[AA_CLASS_FILE]; 801 807 struct aa_perms perms = {}; 802 808 const char *xname = NULL, *info = "change_profile onexec"; ··· 1353 1361 struct aa_label *target, bool stack, 1354 1362 u32 request, struct aa_perms *perms) 1355 1363 { 1356 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 1357 - typeof(*rules), list); 1364 + struct aa_ruleset *rules = profile->label.rules[0]; 1358 1365 const char *info = NULL; 1359 1366 int error = 0; 1360 1367
+2 -4
security/apparmor/file.c
··· 223 223 u32 request, struct path_cond *cond, int flags, 224 224 struct aa_perms *perms) 225 225 { 226 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 227 - typeof(*rules), list); 226 + struct aa_ruleset *rules = profile->label.rules[0]; 228 227 int e = 0; 229 228 230 229 if (profile_unconfined(profile) || ··· 322 323 const struct path *target, char *buffer2, 323 324 struct path_cond *cond) 324 325 { 325 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 326 - typeof(*rules), list); 326 + struct aa_ruleset *rules = profile->label.rules[0]; 327 327 const char *lname, *tname = NULL; 328 328 struct aa_perms lperms = {}, perms; 329 329 const char *info = NULL;
+17 -3
security/apparmor/include/label.h
··· 19 19 #include "lib.h" 20 20 21 21 struct aa_ns; 22 + struct aa_ruleset; 22 23 23 24 #define LOCAL_VEC_ENTRIES 8 24 25 #define DEFINE_VEC(T, V) \ ··· 110 109 int i, j; 111 110 }; 112 111 113 - /* struct aa_label - lazy labeling struct 112 + /* struct aa_label_base - base info of label 114 113 * @count: ref count of active users 115 114 * @node: rbtree position 116 115 * @rcu: rcu callback struct ··· 119 118 * @flags: stale and other flags - values may change under label set lock 120 119 * @secid: secid that references this label 121 120 * @size: number of entries in @ent[] 122 - * @ent: set of profiles for label, actual size determined by @size 121 + * @mediates: bitmask for label_mediates 122 + * profile: label vec when embedded in a profile FLAG_PROFILE is set 123 + * rules: variable length rules in a profile FLAG_PROFILE is set 124 + * vec: vector of profiles comprising the compound label 123 125 */ 124 126 struct aa_label { 125 127 struct kref count; ··· 134 130 u32 secid; 135 131 int size; 136 132 u64 mediates; 137 - struct aa_profile *vec[]; 133 + union { 134 + struct { 135 + /* only used is the label is a profile, size of 136 + * rules[] is determined by the profile 137 + * profile[1] is poison or null as guard 138 + */ 139 + struct aa_profile *profile[2]; 140 + DECLARE_FLEX_ARRAY(struct aa_ruleset *, rules); 141 + }; 142 + DECLARE_FLEX_ARRAY(struct aa_profile *, vec); 143 + }; 138 144 }; 139 145 140 146 #define last_error(E, FN) \
+3 -13
security/apparmor/include/policy.h
··· 165 165 * @secmark: secmark label match info 166 166 */ 167 167 struct aa_ruleset { 168 - struct list_head list; 169 - 170 168 int size; 171 169 172 170 /* TODO: merge policy and file */ ··· 177 179 int secmark_count; 178 180 struct aa_secmark *secmark; 179 181 }; 182 + 180 183 181 184 /* struct aa_attachment - data and rules for a profiles attachment 182 185 * @list: ··· 217 218 * @dents: set of dentries associated with the profile 218 219 * @data: hashtable for free-form policy aa_data 219 220 * @label - label this profile is an extension of 221 + * @rules - label with the rule vec on its end 220 222 * 221 223 * The AppArmor profile contains the basic confinement data. Each profile 222 224 * has a name, and exists in a namespace. The @name and @exec_match are ··· 245 245 const char *disconnected; 246 246 247 247 struct aa_attachment attach; 248 - struct list_head rules; 249 248 250 249 struct aa_loaddata *rawdata; 251 250 unsigned char *hash; ··· 252 253 struct dentry *dents[AAFS_PROF_SIZEOF]; 253 254 struct rhashtable *data; 254 255 256 + int n_rules; 255 257 /* special - variable length must be last entry in profile */ 256 258 struct aa_label label; 257 259 }; ··· 331 331 return state; 332 332 } 333 333 334 - 335 - static inline aa_state_t ANY_RULE_MEDIATES(struct list_head *head, 336 - unsigned char class) 337 - { 338 - struct aa_ruleset *rule; 339 - 340 - /* TODO: change to list walk */ 341 - rule = list_first_entry(head, typeof(*rule), list); 342 - return RULE_MEDIATES(rule, class); 343 - } 344 334 345 335 void aa_compute_profile_mediates(struct aa_profile *profile); 346 336 static inline bool profile_mediates(struct aa_profile *profile,
+1 -2
security/apparmor/ipc.c
··· 80 80 struct aa_label *peer, u32 request, 81 81 struct apparmor_audit_data *ad) 82 82 { 83 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 84 - typeof(*rules), list); 83 + struct aa_ruleset *rules = profile->label.rules[0]; 85 84 struct aa_perms perms; 86 85 aa_state_t state; 87 86
+2 -3
security/apparmor/lsm.c
··· 182 182 struct aa_ruleset *rules; 183 183 kernel_cap_t allowed; 184 184 185 - rules = list_first_entry(&profile->rules, 186 - typeof(*rules), list); 185 + rules = profile->label.rules[0]; 187 186 allowed = aa_profile_capget(profile); 188 187 *effective = cap_intersect(*effective, allowed); 189 188 *permitted = cap_intersect(*permitted, allowed); ··· 635 636 636 637 AA_BUG(!profile); 637 638 638 - rules = list_first_entry(&profile->rules, typeof(*rules), list); 639 + rules = profile->label.rules[0]; 639 640 state = RULE_MEDIATES(rules, AA_CLASS_IO_URING); 640 641 if (state) { 641 642 struct aa_perms perms = { };
+4 -8
security/apparmor/mount.c
··· 311 311 { 312 312 struct aa_perms perms = { }; 313 313 const char *mntpnt = NULL, *info = NULL; 314 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 315 - typeof(*rules), list); 314 + struct aa_ruleset *rules = profile->label.rules[0]; 316 315 int pos, error; 317 316 318 317 AA_BUG(!profile); ··· 370 371 bool binary) 371 372 { 372 373 const char *devname = NULL, *info = NULL; 373 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 374 - typeof(*rules), list); 374 + struct aa_ruleset *rules = profile->label.rules[0]; 375 375 int error = -EACCES; 376 376 377 377 AA_BUG(!profile); ··· 602 604 struct aa_profile *profile, const struct path *path, 603 605 char *buffer) 604 606 { 605 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 606 - typeof(*rules), list); 607 + struct aa_ruleset *rules = profile->label.rules[0]; 607 608 struct aa_perms perms = { }; 608 609 const char *name = NULL, *info = NULL; 609 610 aa_state_t state; ··· 665 668 const struct path *old_path, 666 669 char *old_buffer) 667 670 { 668 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 669 - typeof(*rules), list); 671 + struct aa_ruleset *rules = profile->label.rules[0]; 670 672 const char *old_name, *new_name = NULL, *info = NULL; 671 673 const char *trans_name = NULL; 672 674 struct aa_perms perms = { };
+2 -4
security/apparmor/net.c
··· 251 251 struct apparmor_audit_data *ad, u32 request, u16 family, 252 252 int type, int protocol) 253 253 { 254 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 255 - typeof(*rules), list); 254 + struct aa_ruleset *rules = profile->label.rules[0]; 256 255 struct aa_perms *p = NULL; 257 256 aa_state_t state; 258 257 ··· 361 362 { 362 363 int i, ret; 363 364 struct aa_perms perms = { }; 364 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 365 - typeof(*rules), list); 365 + struct aa_ruleset *rules = profile->label.rules[0]; 366 366 367 367 if (rules->secmark_count == 0) 368 368 return 0;
+26 -19
security/apparmor/policy.c
··· 259 259 struct aa_ruleset *rules; 260 260 261 261 rules = kzalloc(sizeof(*rules), gfp); 262 - if (rules) 263 - INIT_LIST_HEAD(&rules->list); 264 262 265 263 return rules; 266 264 } ··· 275 277 */ 276 278 void aa_free_profile(struct aa_profile *profile) 277 279 { 278 - struct aa_ruleset *rule, *tmp; 279 280 struct rhashtable *rht; 280 281 281 282 AA_DEBUG(DEBUG_POLICY, "%s(%p)\n", __func__, profile); ··· 296 299 * at this point there are no tasks that can have a reference 297 300 * to rules 298 301 */ 299 - list_for_each_entry_safe(rule, tmp, &profile->rules, list) { 300 - list_del_init(&rule->list); 301 - free_ruleset(rule); 302 - } 302 + for (int i = 0; i < profile->n_rules; i++) 303 + free_ruleset(profile->label.rules[i]); 304 + 303 305 kfree_sensitive(profile->dirname); 304 306 305 307 if (profile->data) { ··· 327 331 gfp_t gfp) 328 332 { 329 333 struct aa_profile *profile; 330 - struct aa_ruleset *rules; 331 334 332 - /* freed by free_profile - usually through aa_put_profile */ 333 - profile = kzalloc(struct_size(profile, label.vec, 2), gfp); 335 + /* freed by free_profile - usually through aa_put_profile 336 + * this adds space for a single ruleset in the rules section of the 337 + * label 338 + */ 339 + profile = kzalloc(struct_size(profile, label.rules, 1), gfp); 334 340 if (!profile) 335 341 return NULL; 342 + profile->n_rules = 1; 336 343 337 344 if (!aa_policy_init(&profile->base, NULL, hname, gfp)) 338 345 goto fail; 339 346 if (!aa_label_init(&profile->label, 1, gfp)) 340 347 goto fail; 341 348 342 - INIT_LIST_HEAD(&profile->rules); 343 - 344 349 /* allocate the first ruleset, but leave it empty */ 345 - rules = aa_alloc_ruleset(gfp); 346 - if (!rules) 350 + profile->label.rules[0] = aa_alloc_ruleset(gfp); 351 + if (!profile->label.rules[0]) 347 352 goto fail; 348 - list_add(&rules->list, &profile->rules); 349 353 350 354 /* update being set needed by fs interface */ 351 355 if (!proxy) { ··· 370 374 return NULL; 371 375 } 372 376 377 + static inline bool ANY_RULE_MEDIATES(struct aa_profile *profile, 378 + unsigned char class) 379 + { 380 + int i; 381 + 382 + for (i = 0; i < profile->n_rules; i++) { 383 + if (RULE_MEDIATES(profile->label.rules[i], class)) 384 + return true; 385 + } 386 + return false; 387 + } 388 + 373 389 /* set of rules that are mediated by unconfined */ 374 390 static int unconfined_mediates[] = { AA_CLASS_NS, AA_CLASS_IO_URING, 0 }; 375 391 ··· 394 386 int *pos; 395 387 396 388 for (pos = unconfined_mediates; *pos; pos++) { 397 - if (ANY_RULE_MEDIATES(&profile->rules, AA_CLASS_NS) != 398 - DFA_NOMATCH) 389 + if (ANY_RULE_MEDIATES(profile, *pos)) 399 390 profile->label.mediates |= ((u64) 1) << AA_CLASS_NS; 400 391 } 401 392 return; 402 393 } 403 394 for (c = 0; c <= AA_CLASS_LAST; c++) { 404 - if (ANY_RULE_MEDIATES(&profile->rules, c) != DFA_NOMATCH) 395 + if (ANY_RULE_MEDIATES(profile, c)) 405 396 profile->label.mediates |= ((u64) 1) << c; 406 397 } 407 398 } ··· 653 646 /* TODO: ideally we should inherit abi from parent */ 654 647 profile->label.flags |= FLAG_NULL; 655 648 profile->attach.xmatch = aa_get_pdb(nullpdb); 656 - rules = list_first_entry(&profile->rules, typeof(*rules), list); 649 + rules = profile->label.rules[0]; 657 650 rules->file = aa_get_pdb(nullpdb); 658 651 rules->policy = aa_get_pdb(nullpdb); 659 652 aa_compute_profile_mediates(profile);
+3 -3
security/apparmor/policy_unpack.c
··· 885 885 error = -ENOMEM; 886 886 goto fail; 887 887 } 888 - rules = list_first_entry(&profile->rules, typeof(*rules), list); 888 + rules = profile->label.rules[0]; 889 889 890 890 /* profile renaming is optional */ 891 891 (void) aa_unpack_str(e, &profile->rename, "rename"); ··· 1285 1285 */ 1286 1286 static int verify_profile(struct aa_profile *profile) 1287 1287 { 1288 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 1289 - typeof(*rules), list); 1288 + struct aa_ruleset *rules = profile->label.rules[0]; 1289 + 1290 1290 if (!rules) 1291 1291 return 0; 1292 1292
+3 -8
security/apparmor/resource.c
··· 89 89 struct aa_profile *profile, unsigned int resource, 90 90 struct rlimit *new_rlim) 91 91 { 92 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 93 - typeof(*rules), list); 92 + struct aa_ruleset *rules = profile->label.rules[0]; 94 93 int e = 0; 95 94 96 95 if (rules->rlimits.mask & (1 << resource) && new_rlim->rlim_max > ··· 164 165 * to the lesser of the tasks hard limit and the init tasks soft limit 165 166 */ 166 167 label_for_each_confined(i, old_l, old) { 167 - struct aa_ruleset *rules = list_first_entry(&old->rules, 168 - typeof(*rules), 169 - list); 168 + struct aa_ruleset *rules = old->label.rules[0]; 170 169 if (rules->rlimits.mask) { 171 170 int j; 172 171 ··· 182 185 183 186 /* set any new hard limits as dictated by the new profile */ 184 187 label_for_each_confined(i, new_l, new) { 185 - struct aa_ruleset *rules = list_first_entry(&new->rules, 186 - typeof(*rules), 187 - list); 188 + struct aa_ruleset *rules = new->label.rules[0]; 188 189 int j; 189 190 190 191 if (!rules->rlimits.mask)
+4 -7
security/apparmor/task.c
··· 228 228 struct aa_label *peer, u32 request, 229 229 struct apparmor_audit_data *ad) 230 230 { 231 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 232 - typeof(*rules), list); 231 + struct aa_ruleset *rules = profile->label.rules[0]; 233 232 struct aa_perms perms = { }; 234 233 235 234 ad->subj_cred = cred; ··· 245 246 struct apparmor_audit_data *ad) 246 247 { 247 248 if (profile_unconfined(tracee) || unconfined(tracer) || 248 - !ANY_RULE_MEDIATES(&tracee->rules, AA_CLASS_PTRACE)) 249 + !label_mediates(&tracee->label, AA_CLASS_PTRACE)) 249 250 return 0; 250 251 251 252 return profile_ptrace_perm(cred, tracee, tracer, request, ad); ··· 259 260 if (profile_unconfined(tracer)) 260 261 return 0; 261 262 262 - if (ANY_RULE_MEDIATES(&tracer->rules, AA_CLASS_PTRACE)) 263 + if (label_mediates(&tracer->label, AA_CLASS_PTRACE)) 263 264 return profile_ptrace_perm(cred, tracer, tracee, request, ad); 264 265 265 266 /* profile uses the old style capability check for ptrace */ ··· 323 324 ad->request = request; 324 325 325 326 if (!profile_unconfined(profile)) { 326 - struct aa_ruleset *rules = list_first_entry(&profile->rules, 327 - typeof(*rules), 328 - list); 327 + struct aa_ruleset *rules = profile->label.rules[0]; 329 328 aa_state_t state; 330 329 331 330 state = RULE_MEDIATES(rules, ad->class);