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

apparmor: refactor profile rules and attachments

In preparation for moving from a single set of rules and a single
attachment to multiple rulesets and attachments separate from the
profile refactor attachment information and ruleset info into their
own structures.

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

+308 -239
+13 -14
security/apparmor/apparmorfs.c
··· 611 611 static void profile_query_cb(struct aa_profile *profile, struct aa_perms *perms, 612 612 const char *match_str, size_t match_len) 613 613 { 614 + struct aa_ruleset *rules = &profile->rules; 614 615 struct aa_perms tmp = { }; 615 - struct aa_dfa *dfa; 616 616 aa_state_t state = DFA_NOMATCH; 617 617 618 618 if (profile_unconfined(profile)) 619 619 return; 620 - if (profile->file.dfa && *match_str == AA_CLASS_FILE) { 621 - dfa = profile->file.dfa; 622 - state = aa_dfa_match_len(dfa, 623 - profile->file.start[AA_CLASS_FILE], 620 + if (rules->file.dfa && *match_str == AA_CLASS_FILE) { 621 + state = aa_dfa_match_len(rules->file.dfa, 622 + rules->file.start[AA_CLASS_FILE], 624 623 match_str + 1, match_len - 1); 625 624 if (state) { 626 625 struct path_cond cond = { }; 627 626 628 - tmp = *(aa_lookup_fperms(&(profile->file), state, &cond)); 627 + tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); 629 628 } 630 - } else if (profile->policy.dfa) { 631 - if (!PROFILE_MEDIATES(profile, *match_str)) 629 + } else if (rules->policy.dfa) { 630 + if (!RULE_MEDIATES(rules, *match_str)) 632 631 return; /* no change to current perms */ 633 - dfa = profile->policy.dfa; 634 - state = aa_dfa_match_len(dfa, profile->policy.start[0], 632 + state = aa_dfa_match_len(rules->policy.dfa, 633 + rules->policy.start[0], 635 634 match_str, match_len); 636 635 if (state) 637 - tmp = *aa_lookup_perms(&profile->policy, state); 636 + tmp = *aa_lookup_perms(&rules->policy, state); 638 637 } 639 638 aa_apply_modes_to_perms(profile, &tmp); 640 639 aa_perms_accum_raw(perms, &tmp); ··· 1092 1093 struct aa_proxy *proxy = seq->private; 1093 1094 struct aa_label *label = aa_get_label_rcu(&proxy->label); 1094 1095 struct aa_profile *profile = labels_profile(label); 1095 - if (profile->attach) 1096 - seq_printf(seq, "%s\n", profile->attach); 1097 - else if (profile->xmatch.dfa) 1096 + if (profile->attach.xmatch_str) 1097 + seq_printf(seq, "%s\n", profile->attach.xmatch_str); 1098 + else if (profile->attach.xmatch.dfa) 1098 1099 seq_puts(seq, "<unknown>\n"); 1099 1100 else 1100 1101 seq_printf(seq, "%s\n", profile->base.name);
+7 -5
security/apparmor/capability.c
··· 64 64 static int audit_caps(struct common_audit_data *sa, struct aa_profile *profile, 65 65 int cap, int error) 66 66 { 67 + struct aa_ruleset *rules = &profile->rules; 67 68 struct audit_cache *ent; 68 69 int type = AUDIT_APPARMOR_AUTO; 69 70 ··· 73 72 if (likely(!error)) { 74 73 /* test if auditing is being forced */ 75 74 if (likely((AUDIT_MODE(profile) != AUDIT_ALL) && 76 - !cap_raised(profile->caps.audit, cap))) 75 + !cap_raised(rules->caps.audit, cap))) 77 76 return 0; 78 77 type = AUDIT_APPARMOR_AUDIT; 79 78 } else if (KILL_MODE(profile) || 80 - cap_raised(profile->caps.kill, cap)) { 79 + cap_raised(rules->caps.kill, cap)) { 81 80 type = AUDIT_APPARMOR_KILL; 82 - } else if (cap_raised(profile->caps.quiet, cap) && 81 + } else if (cap_raised(rules->caps.quiet, cap) && 83 82 AUDIT_MODE(profile) != AUDIT_NOQUIET && 84 83 AUDIT_MODE(profile) != AUDIT_ALL) { 85 84 /* quiet auditing */ ··· 115 114 static int profile_capable(struct aa_profile *profile, int cap, 116 115 unsigned int opts, struct common_audit_data *sa) 117 116 { 117 + struct aa_ruleset *rules = &profile->rules; 118 118 int error; 119 119 120 - if (cap_raised(profile->caps.allow, cap) && 121 - !cap_raised(profile->caps.denied, cap)) 120 + if (cap_raised(rules->caps.allow, cap) && 121 + !cap_raised(rules->caps.denied, cap)) 122 122 error = 0; 123 123 else 124 124 error = -EPERM;
+46 -35
security/apparmor/domain.c
··· 81 81 struct aa_profile *tp, 82 82 bool stack, aa_state_t state) 83 83 { 84 + struct aa_ruleset *rules = &profile->rules; 84 85 const char *ns_name; 85 86 86 87 if (stack) 87 - state = aa_dfa_match(profile->file.dfa, state, "&"); 88 + state = aa_dfa_match(rules->file.dfa, state, "&"); 88 89 if (profile->ns == tp->ns) 89 - return aa_dfa_match(profile->file.dfa, state, tp->base.hname); 90 + return aa_dfa_match(rules->file.dfa, state, tp->base.hname); 90 91 91 92 /* try matching with namespace name and then profile */ 92 93 ns_name = aa_ns_name(profile->ns, tp->ns, true); 93 - state = aa_dfa_match_len(profile->file.dfa, state, ":", 1); 94 - state = aa_dfa_match(profile->file.dfa, state, ns_name); 95 - state = aa_dfa_match_len(profile->file.dfa, state, ":", 1); 96 - return aa_dfa_match(profile->file.dfa, state, tp->base.hname); 94 + state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); 95 + state = aa_dfa_match(rules->file.dfa, state, ns_name); 96 + state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); 97 + return aa_dfa_match(rules->file.dfa, state, tp->base.hname); 97 98 } 98 99 99 100 /** ··· 118 117 aa_state_t state, bool subns, u32 request, 119 118 struct aa_perms *perms) 120 119 { 120 + struct aa_ruleset *rules = &profile->rules; 121 121 struct aa_profile *tp; 122 122 struct label_it i; 123 123 struct path_cond cond = { }; ··· 141 139 label_for_each_cont(i, label, tp) { 142 140 if (!aa_ns_visible(profile->ns, tp->ns, subns)) 143 141 continue; 144 - state = aa_dfa_match(profile->file.dfa, state, "//&"); 142 + state = aa_dfa_match(rules->file.dfa, state, "//&"); 145 143 state = match_component(profile, tp, false, state); 146 144 if (!state) 147 145 goto fail; 148 146 } 149 - *perms = *(aa_lookup_fperms(&(profile->file), state, &cond)); 147 + *perms = *(aa_lookup_fperms(&(rules->file), state, &cond)); 150 148 aa_apply_modes_to_perms(profile, perms); 151 149 if ((perms->allow & request) != request) 152 150 return -EACCES; ··· 179 177 aa_state_t start, bool subns, u32 request, 180 178 struct aa_perms *perms) 181 179 { 180 + struct aa_ruleset *rules = &profile->rules; 182 181 struct aa_profile *tp; 183 182 struct label_it i; 184 183 struct aa_perms tmp; ··· 200 197 return 0; 201 198 202 199 next: 203 - tmp = *(aa_lookup_fperms(&(profile->file), state, &cond)); 200 + tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); 204 201 aa_apply_modes_to_perms(profile, &tmp); 205 202 aa_perms_accum(perms, &tmp); 206 203 label_for_each_cont(i, label, tp) { ··· 209 206 state = match_component(profile, tp, stack, start); 210 207 if (!state) 211 208 goto fail; 212 - tmp = *(aa_lookup_fperms(&(profile->file), state, &cond)); 209 + tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); 213 210 aa_apply_modes_to_perms(profile, &tmp); 214 211 aa_perms_accum(perms, &tmp); 215 212 } ··· 299 296 ssize_t size; 300 297 struct dentry *d; 301 298 char *value = NULL; 302 - int value_size = 0, ret = profile->xattr_count; 299 + struct aa_attachment *attach = &profile->attach; 300 + int value_size = 0, ret = attach->xattr_count; 303 301 304 - if (!bprm || !profile->xattr_count) 302 + if (!bprm || !attach->xattr_count) 305 303 return 0; 306 304 might_sleep(); 307 305 308 306 /* transition from exec match to xattr set */ 309 - state = aa_dfa_outofband_transition(profile->xmatch.dfa, state); 307 + state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); 310 308 d = bprm->file->f_path.dentry; 311 309 312 - for (i = 0; i < profile->xattr_count; i++) { 313 - size = vfs_getxattr_alloc(&init_user_ns, d, profile->xattrs[i], 310 + for (i = 0; i < attach->xattr_count; i++) { 311 + size = vfs_getxattr_alloc(&init_user_ns, d, attach->xattrs[i], 314 312 &value, value_size, GFP_KERNEL); 315 313 if (size >= 0) { 316 314 u32 index, perm; ··· 321 317 * that not present xattr can be distinguished from a 0 322 318 * length value or rule that matches any value 323 319 */ 324 - state = aa_dfa_null_transition(profile->xmatch.dfa, 320 + state = aa_dfa_null_transition(attach->xmatch.dfa, 325 321 state); 326 322 /* Check xattr value */ 327 - state = aa_dfa_match_len(profile->xmatch.dfa, state, 323 + state = aa_dfa_match_len(attach->xmatch.dfa, state, 328 324 value, size); 329 - index = ACCEPT_TABLE(profile->xmatch.dfa)[state]; 330 - perm = profile->xmatch.perms[index].allow; 325 + index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; 326 + perm = attach->xmatch.perms[index].allow; 331 327 if (!(perm & MAY_EXEC)) { 332 328 ret = -EINVAL; 333 329 goto out; 334 330 } 335 331 } 336 332 /* transition to next element */ 337 - state = aa_dfa_outofband_transition(profile->xmatch.dfa, state); 333 + state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); 338 334 if (size < 0) { 339 335 /* 340 336 * No xattr match, so verify if transition to ··· 386 382 rcu_read_lock(); 387 383 restart: 388 384 list_for_each_entry_rcu(profile, head, base.list) { 385 + struct aa_attachment *attach = &profile->attach; 386 + 389 387 if (profile->label.flags & FLAG_NULL && 390 388 &profile->label == ns_unconfined(profile->ns)) 391 389 continue; ··· 403 397 * as another profile, signal a conflict and refuse to 404 398 * match. 405 399 */ 406 - if (profile->xmatch.dfa) { 400 + if (attach->xmatch.dfa) { 407 401 unsigned int count; 408 402 aa_state_t state; 409 403 u32 index, perm; 410 404 411 - state = aa_dfa_leftmatch(profile->xmatch.dfa, 412 - profile->xmatch.start[AA_CLASS_XMATCH], 405 + state = aa_dfa_leftmatch(attach->xmatch.dfa, 406 + attach->xmatch.start[AA_CLASS_XMATCH], 413 407 name, &count); 414 - index = ACCEPT_TABLE(profile->xmatch.dfa)[state]; 415 - perm = profile->xmatch.perms[index].allow; 408 + index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; 409 + perm = attach->xmatch.perms[index].allow; 416 410 /* any accepting state means a valid match. */ 417 411 if (perm & MAY_EXEC) { 418 412 int ret = 0; ··· 420 414 if (count < candidate_len) 421 415 continue; 422 416 423 - if (bprm && profile->xattr_count) { 417 + if (bprm && attach->xattr_count) { 424 418 long rev = READ_ONCE(ns->revision); 425 419 426 420 if (!aa_get_profile_not0(profile)) ··· 459 453 * xattrs, or a longer match 460 454 */ 461 455 candidate = profile; 462 - candidate_len = max(count, profile->xmatch_len); 456 + candidate_len = max(count, attach->xmatch_len); 463 457 candidate_xattrs = ret; 464 458 conflict = false; 465 459 } ··· 503 497 struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, 504 498 const char **name) 505 499 { 500 + struct aa_ruleset *rules = &profile->rules; 506 501 struct aa_label *label = NULL; 507 502 u32 xtype = xindex & AA_X_TYPE_MASK; 508 503 int index = xindex & AA_X_INDEX_MASK; ··· 514 507 /* TODO: move lookup parsing to unpack time so this is a straight 515 508 * index into the resultant label 516 509 */ 517 - for (*name = profile->file.trans.table[index]; !label && *name; 510 + for (*name = rules->file.trans.table[index]; !label && *name; 518 511 *name = next_name(xtype, *name)) { 519 512 if (xindex & AA_X_CHILD) { 520 513 struct aa_profile *new_profile; ··· 553 546 const char **lookupname, 554 547 const char **info) 555 548 { 549 + struct aa_ruleset *rules = &profile->rules; 556 550 struct aa_label *new = NULL; 557 551 struct aa_ns *ns = profile->ns; 558 552 u32 xtype = xindex & AA_X_TYPE_MASK; ··· 566 558 break; 567 559 case AA_X_TABLE: 568 560 /* TODO: fix when perm mapping done at unload */ 569 - stack = profile->file.trans.table[xindex & AA_X_INDEX_MASK]; 561 + stack = rules->file.trans.table[xindex & AA_X_INDEX_MASK]; 570 562 if (*stack != '&') { 571 563 /* released by caller */ 572 564 new = x_table_lookup(profile, xindex, lookupname); ··· 620 612 char *buffer, struct path_cond *cond, 621 613 bool *secure_exec) 622 614 { 615 + struct aa_ruleset *rules = &profile->rules; 623 616 struct aa_label *new = NULL; 624 617 const char *info = NULL, *name = NULL, *target = NULL; 625 - aa_state_t state = profile->file.start[AA_CLASS_FILE]; 618 + aa_state_t state = rules->file.start[AA_CLASS_FILE]; 626 619 struct aa_perms perms = {}; 627 620 bool nonewprivs = false; 628 621 int error = 0; ··· 657 648 } 658 649 659 650 /* find exec permissions for name */ 660 - state = aa_str_perms(&(profile->file), state, name, cond, &perms); 651 + state = aa_str_perms(&(rules->file), state, name, cond, &perms); 661 652 if (perms.allow & MAY_EXEC) { 662 653 /* exec permission determine how to transition */ 663 654 new = x_to_label(profile, bprm, name, perms.xindex, &target, ··· 719 710 char *buffer, struct path_cond *cond, 720 711 bool *secure_exec) 721 712 { 722 - aa_state_t state = profile->file.start[AA_CLASS_FILE]; 713 + struct aa_ruleset *rules = &profile->rules; 714 + aa_state_t state = rules->file.start[AA_CLASS_FILE]; 723 715 struct aa_perms perms = {}; 724 716 const char *xname = NULL, *info = "change_profile onexec"; 725 717 int error = -EACCES; ··· 753 743 } 754 744 755 745 /* find exec permissions for name */ 756 - state = aa_str_perms(&(profile->file), state, xname, cond, &perms); 746 + state = aa_str_perms(&(rules->file), state, xname, cond, &perms); 757 747 if (!(perms.allow & AA_MAY_ONEXEC)) { 758 748 info = "no change_onexec valid for executable"; 759 749 goto audit; ··· 762 752 * onexec permission is linked to exec with a standard pairing 763 753 * exec\0change_profile 764 754 */ 765 - state = aa_dfa_null_transition(profile->file.dfa, state); 755 + state = aa_dfa_null_transition(rules->file.dfa, state); 766 756 error = change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC, 767 757 state, &perms); 768 758 if (error) { ··· 1259 1249 struct aa_label *target, bool stack, 1260 1250 u32 request, struct aa_perms *perms) 1261 1251 { 1252 + struct aa_ruleset *rules = &profile->rules; 1262 1253 const char *info = NULL; 1263 1254 int error = 0; 1264 1255 1265 1256 if (!error) 1266 1257 error = change_profile_perms(profile, target, stack, request, 1267 - profile->file.start[AA_CLASS_FILE], 1258 + rules->file.start[AA_CLASS_FILE], 1268 1259 perms); 1269 1260 if (error) 1270 1261 error = aa_audit_file(profile, perms, op, request, name,
+8 -6
security/apparmor/file.c
··· 224 224 u32 request, struct path_cond *cond, int flags, 225 225 struct aa_perms *perms) 226 226 { 227 + struct aa_ruleset *rules = &profile->rules; 227 228 int e = 0; 228 229 229 230 if (profile_unconfined(profile)) 230 231 return 0; 231 - aa_str_perms(&(profile->file), profile->file.start[AA_CLASS_FILE], 232 + aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], 232 233 name, cond, perms); 233 234 if (request & ~perms->allow) 234 235 e = -EACCES; ··· 317 316 const struct path *target, char *buffer2, 318 317 struct path_cond *cond) 319 318 { 319 + struct aa_ruleset *rules = &profile->rules; 320 320 const char *lname, *tname = NULL; 321 321 struct aa_perms lperms = {}, perms; 322 322 const char *info = NULL; ··· 338 336 339 337 error = -EACCES; 340 338 /* aa_str_perms - handles the case of the dfa being NULL */ 341 - state = aa_str_perms(&(profile->file), 342 - profile->file.start[AA_CLASS_FILE], lname, 339 + state = aa_str_perms(&(rules->file), 340 + rules->file.start[AA_CLASS_FILE], lname, 343 341 cond, &lperms); 344 342 345 343 if (!(lperms.allow & AA_MAY_LINK)) 346 344 goto audit; 347 345 348 346 /* test to see if target can be paired with link */ 349 - state = aa_dfa_null_transition(profile->file.dfa, state); 350 - aa_str_perms(&(profile->file), state, tname, cond, &perms); 347 + state = aa_dfa_null_transition(rules->file.dfa, state); 348 + aa_str_perms(&(rules->file), state, tname, cond, &perms); 351 349 352 350 /* force audit/quiet masks for link are stored in the second entry 353 351 * in the link pair. ··· 369 367 /* Do link perm subset test requiring allowed permission on link are 370 368 * a subset of the allowed permissions on target. 371 369 */ 372 - aa_str_perms(&(profile->file), profile->file.start[AA_CLASS_FILE], 370 + aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE], 373 371 tname, cond, &perms); 374 372 375 373 /* AA_MAY_LINK is not considered in the subset test */
+5 -4
security/apparmor/include/label.h
··· 261 261 struct label_it i; \ 262 262 int ret = 0; \ 263 263 label_for_each(i, (L), profile) { \ 264 - if (PROFILE_MEDIATES(profile, (C))) { \ 264 + if (RULE_MEDIATES(&profile->rules, (C))) { \ 265 265 ret = 1; \ 266 266 break; \ 267 267 } \ ··· 357 357 358 358 359 359 struct aa_perms; 360 - int aa_label_match(struct aa_profile *profile, struct aa_label *label, 361 - aa_state_t state, bool subns, u32 request, 362 - struct aa_perms *perms); 360 + struct aa_ruleset; 361 + int aa_label_match(struct aa_profile *profile, struct aa_ruleset *rules, 362 + struct aa_label *label, aa_state_t state, bool subns, 363 + u32 request, struct aa_perms *perms); 363 364 364 365 365 366 /**
+2 -1
security/apparmor/include/perms.h
··· 207 207 struct aa_perms *perms); 208 208 void aa_perms_accum(struct aa_perms *accum, struct aa_perms *addend); 209 209 void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend); 210 - void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label, 210 + void aa_profile_match_label(struct aa_profile *profile, 211 + struct aa_ruleset *rules, struct aa_label *label, 211 212 int type, u32 request, struct aa_perms *perms); 212 213 int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target, 213 214 u32 request, int type, u32 *deny,
+51 -33
security/apparmor/include/policy.h
··· 123 123 struct rhash_head head; 124 124 }; 125 125 126 + /* struct aa_ruleset - data covering mediation rules 127 + * @size: the memory consumed by this ruleset 128 + * @policy: general match rules governing policy 129 + * @file: The set of rules governing basic file access and domain transitions 130 + * @caps: capabilities for the profile 131 + * @rlimits: rlimits for the profile 132 + * @secmark_count: number of secmark entries 133 + * @secmark: secmark label match info 134 + */ 135 + struct aa_ruleset { 136 + int size; 137 + 138 + /* TODO: merge policy and file */ 139 + struct aa_policydb policy; 140 + struct aa_policydb file; 141 + struct aa_caps caps; 142 + 143 + struct aa_rlimit rlimits; 144 + 145 + int secmark_count; 146 + struct aa_secmark *secmark; 147 + }; 148 + 149 + /* struct aa_attachment - data and rules for a profiles attachment 150 + * @xmatch_str: human readable attachment string 151 + * @xmatch: optional extended matching for unconfined executables names 152 + * @xmatch_len: xmatch prefix len, used to determine xmatch priority 153 + * @xattr_count: number of xattrs in table 154 + * @xattrs: table of xattrs 155 + */ 156 + struct aa_attachment { 157 + const char *xmatch_str; 158 + struct aa_policydb xmatch; 159 + unsigned int xmatch_len; 160 + int xattr_count; 161 + char **xattrs; 162 + }; 126 163 127 164 /* struct aa_profile - basic confinement data 128 165 * @base - base components of the profile (name, refcount, lists, lock ...) ··· 167 130 * @parent: parent of profile 168 131 * @ns: namespace the profile is in 169 132 * @rename: optional profile name that this profile renamed 170 - * @attach: human readable attachment string 171 - * @xmatch: optional extended matching for unconfined executables names 172 - * @xmatch_len: xmatch prefix len, used to determine xmatch priority 133 + * 173 134 * @audit: the auditing mode of the profile 174 135 * @mode: the enforcement mode of the profile 175 136 * @path_flags: flags controlling path generation behavior 176 137 * @disconnected: what to prepend if attach_disconnected is specified 177 - * @size: the memory consumed by this profiles rules 178 - * @policy: general match rules governing policy 179 - * @file: The set of rules governing basic file access and domain transitions 180 - * @caps: capabilities for the profile 181 - * @rlimits: rlimits for the profile 138 + * @attach: attachment rules for the profile 139 + * @rules: rules to be enforced 182 140 * 183 141 * @dents: dentries for the profiles file entries in apparmorfs 184 142 * @dirname: name of the profile dir in apparmorfs ··· 198 166 struct aa_ns *ns; 199 167 const char *rename; 200 168 201 - const char *attach; 202 - struct aa_policydb xmatch; 203 - unsigned int xmatch_len; 204 - 205 169 enum audit_mode audit; 206 170 long mode; 207 171 u32 path_flags; 208 172 const char *disconnected; 209 - int size; 210 173 211 - struct aa_policydb policy; 212 - struct aa_policydb file; 213 - struct aa_caps caps; 214 - 215 - int xattr_count; 216 - char **xattrs; 217 - 218 - struct aa_rlimit rlimits; 219 - 220 - int secmark_count; 221 - struct aa_secmark *secmark; 174 + struct aa_attachment attach; 175 + struct aa_ruleset rules; 222 176 223 177 struct aa_loaddata *rawdata; 224 178 unsigned char *hash; ··· 265 247 return labels_profile(aa_get_newest_label(&p->label)); 266 248 } 267 249 268 - static inline aa_state_t PROFILE_MEDIATES(struct aa_profile *profile, 269 - unsigned char class) 250 + static inline aa_state_t RULE_MEDIATES(struct aa_ruleset *rules, 251 + unsigned char class) 270 252 { 271 253 if (class <= AA_CLASS_LAST) 272 - return profile->policy.start[class]; 254 + return rules->policy.start[class]; 273 255 else 274 - return aa_dfa_match_len(profile->policy.dfa, 275 - profile->policy.start[0], &class, 1); 256 + return aa_dfa_match_len(rules->policy.dfa, 257 + rules->policy.start[0], &class, 1); 276 258 } 277 259 278 - static inline aa_state_t PROFILE_MEDIATES_AF(struct aa_profile *profile, 279 - u16 AF) { 280 - aa_state_t state = PROFILE_MEDIATES(profile, AA_CLASS_NET); 260 + static inline aa_state_t RULE_MEDIATES_AF(struct aa_ruleset *rules, u16 AF) 261 + { 262 + aa_state_t state = RULE_MEDIATES(rules, AA_CLASS_NET); 281 263 __be16 be_af = cpu_to_be16(AF); 282 264 283 265 if (!state) 284 266 return DFA_NOMATCH; 285 - return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2); 267 + return aa_dfa_match_len(rules->policy.dfa, state, (char *) &be_af, 2); 286 268 } 287 269 288 270 /**
+5 -4
security/apparmor/ipc.c
··· 78 78 struct aa_label *peer, u32 request, 79 79 struct common_audit_data *sa) 80 80 { 81 + struct aa_ruleset *rules = &profile->rules; 81 82 struct aa_perms perms; 82 83 aa_state_t state; 83 84 84 85 if (profile_unconfined(profile) || 85 - !PROFILE_MEDIATES(profile, AA_CLASS_SIGNAL)) 86 + !RULE_MEDIATES(rules, AA_CLASS_SIGNAL)) 86 87 return 0; 87 88 88 89 aad(sa)->peer = peer; 89 90 /* TODO: secondary cache check <profile, profile, perm> */ 90 - state = aa_dfa_next(profile->policy.dfa, 91 - profile->policy.start[AA_CLASS_SIGNAL], 91 + state = aa_dfa_next(rules->policy.dfa, 92 + rules->policy.start[AA_CLASS_SIGNAL], 92 93 aad(sa)->signal); 93 - aa_label_match(profile, peer, state, false, request, &perms); 94 + aa_label_match(profile, rules, peer, state, false, request, &perms); 94 95 aa_apply_modes_to_perms(profile, &perms); 95 96 return aa_check_perms(profile, &perms, request, sa, audit_signal_cb); 96 97 }
+25 -20
security/apparmor/label.c
··· 1266 1266 * visibility test. 1267 1267 */ 1268 1268 static inline aa_state_t match_component(struct aa_profile *profile, 1269 + struct aa_ruleset *rules, 1269 1270 struct aa_profile *tp, 1270 1271 aa_state_t state) 1271 1272 { 1272 1273 const char *ns_name; 1273 1274 1274 1275 if (profile->ns == tp->ns) 1275 - return aa_dfa_match(profile->policy.dfa, state, tp->base.hname); 1276 + return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); 1276 1277 1277 1278 /* try matching with namespace name and then profile */ 1278 1279 ns_name = aa_ns_name(profile->ns, tp->ns, true); 1279 - state = aa_dfa_match_len(profile->policy.dfa, state, ":", 1); 1280 - state = aa_dfa_match(profile->policy.dfa, state, ns_name); 1281 - state = aa_dfa_match_len(profile->policy.dfa, state, ":", 1); 1282 - return aa_dfa_match(profile->policy.dfa, state, tp->base.hname); 1280 + state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1); 1281 + state = aa_dfa_match(rules->policy.dfa, state, ns_name); 1282 + state = aa_dfa_match_len(rules->policy.dfa, state, ":", 1); 1283 + return aa_dfa_match(rules->policy.dfa, state, tp->base.hname); 1283 1284 } 1284 1285 1285 1286 /** ··· 1299 1298 * check to be stacked. 1300 1299 */ 1301 1300 static int label_compound_match(struct aa_profile *profile, 1301 + struct aa_ruleset *rules, 1302 1302 struct aa_label *label, 1303 1303 aa_state_t state, bool subns, u32 request, 1304 1304 struct aa_perms *perms) ··· 1311 1309 label_for_each(i, label, tp) { 1312 1310 if (!aa_ns_visible(profile->ns, tp->ns, subns)) 1313 1311 continue; 1314 - state = match_component(profile, tp, state); 1312 + state = match_component(profile, rules, tp, state); 1315 1313 if (!state) 1316 1314 goto fail; 1317 1315 goto next; ··· 1325 1323 label_for_each_cont(i, label, tp) { 1326 1324 if (!aa_ns_visible(profile->ns, tp->ns, subns)) 1327 1325 continue; 1328 - state = aa_dfa_match(profile->policy.dfa, state, "//&"); 1329 - state = match_component(profile, tp, state); 1326 + state = aa_dfa_match(rules->policy.dfa, state, "//&"); 1327 + state = match_component(profile, rules, tp, state); 1330 1328 if (!state) 1331 1329 goto fail; 1332 1330 } 1333 - *perms = *aa_lookup_perms(&profile->policy, state); 1331 + *perms = *aa_lookup_perms(&rules->policy, state); 1334 1332 aa_apply_modes_to_perms(profile, perms); 1335 1333 if ((perms->allow & request) != request) 1336 1334 return -EACCES; ··· 1345 1343 /** 1346 1344 * label_components_match - find perms for all subcomponents of a label 1347 1345 * @profile: profile to find perms for 1346 + * @rules: ruleset to search 1348 1347 * @label: label to check access permissions for 1349 1348 * @start: state to start match in 1350 1349 * @subns: whether to do permission checks on components in a subns ··· 1359 1356 * check to be stacked. 1360 1357 */ 1361 1358 static int label_components_match(struct aa_profile *profile, 1359 + struct aa_ruleset *rules, 1362 1360 struct aa_label *label, aa_state_t start, 1363 1361 bool subns, u32 request, 1364 1362 struct aa_perms *perms) ··· 1373 1369 label_for_each(i, label, tp) { 1374 1370 if (!aa_ns_visible(profile->ns, tp->ns, subns)) 1375 1371 continue; 1376 - state = match_component(profile, tp, start); 1372 + state = match_component(profile, rules, tp, start); 1377 1373 if (!state) 1378 1374 goto fail; 1379 1375 goto next; ··· 1383 1379 return 0; 1384 1380 1385 1381 next: 1386 - tmp = *aa_lookup_perms(&profile->policy, state); 1382 + tmp = *aa_lookup_perms(&rules->policy, state); 1387 1383 aa_apply_modes_to_perms(profile, &tmp); 1388 1384 aa_perms_accum(perms, &tmp); 1389 1385 label_for_each_cont(i, label, tp) { 1390 1386 if (!aa_ns_visible(profile->ns, tp->ns, subns)) 1391 1387 continue; 1392 - state = match_component(profile, tp, start); 1388 + state = match_component(profile, rules, tp, start); 1393 1389 if (!state) 1394 1390 goto fail; 1395 - tmp = *aa_lookup_perms(&profile->policy, state); 1391 + tmp = *aa_lookup_perms(&rules->policy, state); 1396 1392 aa_apply_modes_to_perms(profile, &tmp); 1397 1393 aa_perms_accum(perms, &tmp); 1398 1394 } ··· 1410 1406 /** 1411 1407 * aa_label_match - do a multi-component label match 1412 1408 * @profile: profile to match against (NOT NULL) 1409 + * @rules: ruleset to search 1413 1410 * @label: label to match (NOT NULL) 1414 1411 * @state: state to start in 1415 1412 * @subns: whether to match subns components ··· 1419 1414 * 1420 1415 * Returns: the state the match finished in, may be the none matching state 1421 1416 */ 1422 - int aa_label_match(struct aa_profile *profile, struct aa_label *label, 1423 - aa_state_t state, bool subns, u32 request, 1424 - struct aa_perms *perms) 1417 + int aa_label_match(struct aa_profile *profile, struct aa_ruleset *rules, 1418 + struct aa_label *label, aa_state_t state, bool subns, 1419 + u32 request, struct aa_perms *perms) 1425 1420 { 1426 - int error = label_compound_match(profile, label, state, subns, request, 1427 - perms); 1421 + int error = label_compound_match(profile, rules, label, state, subns, 1422 + request, perms); 1428 1423 if (!error) 1429 1424 return error; 1430 1425 1431 1426 *perms = allperms; 1432 - return label_components_match(profile, label, state, subns, request, 1433 - perms); 1427 + return label_components_match(profile, rules, label, state, subns, 1428 + request, perms); 1434 1429 } 1435 1430 1436 1431
+8 -5
security/apparmor/lib.c
··· 331 331 perms->prompt = ALL_PERMS_MASK; 332 332 } 333 333 334 - void aa_profile_match_label(struct aa_profile *profile, struct aa_label *label, 334 + void aa_profile_match_label(struct aa_profile *profile, 335 + struct aa_ruleset *rules, 336 + struct aa_label *label, 335 337 int type, u32 request, struct aa_perms *perms) 336 338 { 337 339 /* TODO: doesn't yet handle extended types */ 338 340 aa_state_t state; 339 341 340 - state = aa_dfa_next(profile->policy.dfa, 341 - profile->policy.start[AA_CLASS_LABEL], 342 + state = aa_dfa_next(rules->policy.dfa, 343 + rules->policy.start[AA_CLASS_LABEL], 342 344 type); 343 - aa_label_match(profile, label, state, false, request, perms); 345 + aa_label_match(profile, rules, label, state, false, request, perms); 344 346 } 345 347 346 348 ··· 357 355 aad(sa)->peer = &target->label; 358 356 aad(sa)->request = request; 359 357 360 - aa_profile_match_label(profile, &target->label, type, request, &perms); 358 + aa_profile_match_label(profile, &profile->rules, &target->label, type, 359 + request, &perms); 361 360 aa_apply_modes_to_perms(profile, &perms); 362 361 *deny |= request & perms.deny; 363 362 return aa_check_perms(profile, &perms, request, sa, aa_audit_perms_cb);
+2 -2
security/apparmor/lsm.c
··· 166 166 if (COMPLAIN_MODE(profile)) 167 167 continue; 168 168 *effective = cap_intersect(*effective, 169 - profile->caps.allow); 169 + profile->rules.caps.allow); 170 170 *permitted = cap_intersect(*permitted, 171 - profile->caps.allow); 171 + profile->rules.caps.allow); 172 172 } 173 173 } 174 174 rcu_read_unlock();
+17 -14
security/apparmor/mount.c
··· 303 303 { 304 304 struct aa_perms perms = { }; 305 305 const char *mntpnt = NULL, *info = NULL; 306 + struct aa_ruleset *rules = &profile->rules; 306 307 int pos, error; 307 308 308 309 AA_BUG(!profile); 309 310 AA_BUG(!mntpath); 310 311 AA_BUG(!buffer); 311 312 312 - if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT)) 313 + if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT)) 313 314 return 0; 314 315 315 316 error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer, ··· 325 324 } 326 325 327 326 error = -EACCES; 328 - pos = do_match_mnt(&profile->policy, 329 - profile->policy.start[AA_CLASS_MOUNT], 327 + pos = do_match_mnt(&rules->policy, 328 + rules->policy.start[AA_CLASS_MOUNT], 330 329 mntpnt, devname, type, flags, data, binary, &perms); 331 330 if (pos) { 332 331 info = mnt_info_table[pos]; ··· 364 363 AA_BUG(!profile); 365 364 AA_BUG(devpath && !devbuffer); 366 365 367 - if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT)) 366 + if (!RULE_MEDIATES(&profile->rules, AA_CLASS_MOUNT)) 368 367 return 0; 369 368 370 369 if (devpath) { ··· 566 565 static int profile_umount(struct aa_profile *profile, const struct path *path, 567 566 char *buffer) 568 567 { 568 + struct aa_ruleset *rules = &profile->rules; 569 569 struct aa_perms perms = { }; 570 570 const char *name = NULL, *info = NULL; 571 571 aa_state_t state; ··· 575 573 AA_BUG(!profile); 576 574 AA_BUG(!path); 577 575 578 - if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT)) 576 + if (!RULE_MEDIATES(rules, AA_CLASS_MOUNT)) 579 577 return 0; 580 578 581 579 error = aa_path_name(path, path_flags(profile, path), buffer, &name, ··· 583 581 if (error) 584 582 goto audit; 585 583 586 - state = aa_dfa_match(profile->policy.dfa, 587 - profile->policy.start[AA_CLASS_MOUNT], 584 + state = aa_dfa_match(rules->policy.dfa, 585 + rules->policy.start[AA_CLASS_MOUNT], 588 586 name); 589 - perms = *aa_lookup_perms(&profile->policy, state); 587 + perms = *aa_lookup_perms(&rules->policy, state); 590 588 if (AA_MAY_UMOUNT & ~perms.allow) 591 589 error = -EACCES; 592 590 ··· 626 624 const struct path *old_path, 627 625 char *old_buffer) 628 626 { 627 + struct aa_ruleset *rules = &profile->rules; 629 628 const char *old_name, *new_name = NULL, *info = NULL; 630 629 const char *trans_name = NULL; 631 630 struct aa_perms perms = { }; ··· 638 635 AA_BUG(!old_path); 639 636 640 637 if (profile_unconfined(profile) || 641 - !PROFILE_MEDIATES(profile, AA_CLASS_MOUNT)) 638 + !RULE_MEDIATES(rules, AA_CLASS_MOUNT)) 642 639 return aa_get_newest_label(&profile->label); 643 640 644 641 error = aa_path_name(old_path, path_flags(profile, old_path), ··· 653 650 goto audit; 654 651 655 652 error = -EACCES; 656 - state = aa_dfa_match(profile->policy.dfa, 657 - profile->policy.start[AA_CLASS_MOUNT], 653 + state = aa_dfa_match(rules->policy.dfa, 654 + rules->policy.start[AA_CLASS_MOUNT], 658 655 new_name); 659 - state = aa_dfa_null_transition(profile->policy.dfa, state); 660 - state = aa_dfa_match(profile->policy.dfa, state, old_name); 661 - perms = *aa_lookup_perms(&profile->policy, state); 656 + state = aa_dfa_null_transition(rules->policy.dfa, state); 657 + state = aa_dfa_match(rules->policy.dfa, state, old_name); 658 + perms = *aa_lookup_perms(&rules->policy, state); 662 659 663 660 if (AA_MAY_PIVOTROOT & perms.allow) 664 661 error = 0;
+13 -11
security/apparmor/net.c
··· 108 108 int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa, 109 109 u32 request, u16 family, int type) 110 110 { 111 + struct aa_ruleset *rules = &profile->rules; 111 112 struct aa_perms perms = { }; 112 113 aa_state_t state; 113 114 __be16 buffer[2]; ··· 118 117 119 118 if (profile_unconfined(profile)) 120 119 return 0; 121 - state = PROFILE_MEDIATES(profile, AA_CLASS_NET); 120 + state = RULE_MEDIATES(rules, AA_CLASS_NET); 122 121 if (!state) 123 122 return 0; 124 123 125 124 buffer[0] = cpu_to_be16(family); 126 125 buffer[1] = cpu_to_be16((u16) type); 127 - state = aa_dfa_match_len(profile->policy.dfa, state, (char *) &buffer, 126 + state = aa_dfa_match_len(rules->policy.dfa, state, (char *) &buffer, 128 127 4); 129 - perms = *aa_lookup_perms(&profile->policy, state); 128 + perms = *aa_lookup_perms(&rules->policy, state); 130 129 aa_apply_modes_to_perms(profile, &perms); 131 130 132 131 return aa_check_perms(profile, &perms, request, sa, audit_net_cb); ··· 217 216 { 218 217 int i, ret; 219 218 struct aa_perms perms = { }; 219 + struct aa_ruleset *rules = &profile->rules; 220 220 221 - if (profile->secmark_count == 0) 221 + if (rules->secmark_count == 0) 222 222 return 0; 223 223 224 - for (i = 0; i < profile->secmark_count; i++) { 225 - if (!profile->secmark[i].secid) { 226 - ret = apparmor_secmark_init(&profile->secmark[i]); 224 + for (i = 0; i < rules->secmark_count; i++) { 225 + if (!rules->secmark[i].secid) { 226 + ret = apparmor_secmark_init(&rules->secmark[i]); 227 227 if (ret) 228 228 return ret; 229 229 } 230 230 231 - if (profile->secmark[i].secid == secid || 232 - profile->secmark[i].secid == AA_SECID_WILDCARD) { 233 - if (profile->secmark[i].deny) 231 + if (rules->secmark[i].secid == secid || 232 + rules->secmark[i].secid == AA_SECID_WILDCARD) { 233 + if (rules->secmark[i].deny) 234 234 perms.deny = ALL_PERMS_MASK; 235 235 else 236 236 perms.allow = ALL_PERMS_MASK; 237 237 238 - if (profile->secmark[i].audit) 238 + if (rules->secmark[i].audit) 239 239 perms.audit = ALL_PERMS_MASK; 240 240 } 241 241 }
+29 -15
security/apparmor/policy.c
··· 193 193 kfree_sensitive(data); 194 194 } 195 195 196 + static void free_attachment(struct aa_attachment *attach) 197 + { 198 + int i; 199 + 200 + for (i = 0; i < attach->xattr_count; i++) 201 + kfree_sensitive(attach->xattrs[i]); 202 + kfree_sensitive(attach->xattrs); 203 + aa_destroy_policydb(&attach->xmatch); 204 + } 205 + 206 + static void free_ruleset(struct aa_ruleset *rules) 207 + { 208 + int i; 209 + 210 + aa_destroy_policydb(&rules->file); 211 + aa_destroy_policydb(&rules->policy); 212 + aa_free_cap_rules(&rules->caps); 213 + aa_free_rlimit_rules(&rules->rlimits); 214 + 215 + for (i = 0; i < rules->secmark_count; i++) 216 + kfree_sensitive(rules->secmark[i].label); 217 + kfree_sensitive(rules->secmark); 218 + } 219 + 196 220 /** 197 221 * aa_free_profile - free a profile 198 222 * @profile: the profile to free (MAYBE NULL) ··· 230 206 void aa_free_profile(struct aa_profile *profile) 231 207 { 232 208 struct rhashtable *rht; 233 - int i; 234 209 235 210 AA_DEBUG("%s(%p)\n", __func__, profile); 236 211 ··· 243 220 aa_put_ns(profile->ns); 244 221 kfree_sensitive(profile->rename); 245 222 246 - aa_destroy_policydb(&profile->file); 247 - aa_free_cap_rules(&profile->caps); 248 - aa_free_rlimit_rules(&profile->rlimits); 249 - 250 - for (i = 0; i < profile->xattr_count; i++) 251 - kfree_sensitive(profile->xattrs[i]); 252 - kfree_sensitive(profile->xattrs); 253 - for (i = 0; i < profile->secmark_count; i++) 254 - kfree_sensitive(profile->secmark[i].label); 255 - kfree_sensitive(profile->secmark); 223 + free_attachment(&profile->attach); 224 + free_ruleset(&profile->rules); 256 225 kfree_sensitive(profile->dirname); 257 - aa_destroy_policydb(&profile->xmatch); 258 - aa_destroy_policydb(&profile->policy); 226 + 259 227 if (profile->data) { 260 228 rht = profile->data; 261 229 profile->data = NULL; ··· 558 544 /* released on free_profile */ 559 545 rcu_assign_pointer(profile->parent, aa_get_profile(parent)); 560 546 profile->ns = aa_get_ns(parent->ns); 561 - profile->file.dfa = aa_get_dfa(nulldfa); 562 - profile->policy.dfa = aa_get_dfa(nulldfa); 547 + profile->rules.file.dfa = aa_get_dfa(nulldfa); 548 + profile->rules.policy.dfa = aa_get_dfa(nulldfa); 563 549 564 550 mutex_lock_nested(&profile->ns->lock, profile->ns->level); 565 551 p = __find_child(&parent->base.profiles, bname);
+2 -2
security/apparmor/policy_ns.c
··· 91 91 profile->label.flags |= FLAG_IX_ON_NAME_ERROR | 92 92 FLAG_IMMUTIBLE | FLAG_NS_COUNT | FLAG_UNCONFINED; 93 93 profile->mode = APPARMOR_UNCONFINED; 94 - profile->file.dfa = aa_get_dfa(nulldfa); 95 - profile->policy.dfa = aa_get_dfa(nulldfa); 94 + profile->rules.file.dfa = aa_get_dfa(nulldfa); 95 + profile->rules.policy.dfa = aa_get_dfa(nulldfa); 96 96 97 97 return profile; 98 98 }
+62 -56
security/apparmor/policy_unpack.c
··· 556 556 557 557 if (unpack_array(e, NULL, &size) != TRI_TRUE) 558 558 goto fail; 559 - profile->xattr_count = size; 560 - profile->xattrs = kcalloc(size, sizeof(char *), GFP_KERNEL); 561 - if (!profile->xattrs) 559 + profile->attach.xattr_count = size; 560 + profile->attach.xattrs = kcalloc(size, sizeof(char *), GFP_KERNEL); 561 + if (!profile->attach.xattrs) 562 562 goto fail; 563 563 for (i = 0; i < size; i++) { 564 - if (!unpack_strdup(e, &profile->xattrs[i], NULL)) 564 + if (!unpack_strdup(e, &profile->attach.xattrs[i], NULL)) 565 565 goto fail; 566 566 } 567 567 if (!unpack_nameX(e, AA_ARRAYEND, NULL)) ··· 579 579 580 580 static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile) 581 581 { 582 + struct aa_ruleset *rules = &profile->rules; 582 583 void *pos = e->pos; 583 584 u16 size; 584 585 int i; ··· 588 587 if (unpack_array(e, NULL, &size) != TRI_TRUE) 589 588 goto fail; 590 589 591 - profile->secmark = kcalloc(size, sizeof(struct aa_secmark), 590 + rules->secmark = kcalloc(size, sizeof(struct aa_secmark), 592 591 GFP_KERNEL); 593 - if (!profile->secmark) 592 + if (!rules->secmark) 594 593 goto fail; 595 594 596 - profile->secmark_count = size; 595 + rules->secmark_count = size; 597 596 598 597 for (i = 0; i < size; i++) { 599 - if (!unpack_u8(e, &profile->secmark[i].audit, NULL)) 598 + if (!unpack_u8(e, &rules->secmark[i].audit, NULL)) 600 599 goto fail; 601 - if (!unpack_u8(e, &profile->secmark[i].deny, NULL)) 600 + if (!unpack_u8(e, &rules->secmark[i].deny, NULL)) 602 601 goto fail; 603 - if (!unpack_strdup(e, &profile->secmark[i].label, NULL)) 602 + if (!unpack_strdup(e, &rules->secmark[i].label, NULL)) 604 603 goto fail; 605 604 } 606 605 if (!unpack_nameX(e, AA_ARRAYEND, NULL)) ··· 612 611 return true; 613 612 614 613 fail: 615 - if (profile->secmark) { 614 + if (rules->secmark) { 616 615 for (i = 0; i < size; i++) 617 - kfree(profile->secmark[i].label); 618 - kfree(profile->secmark); 619 - profile->secmark_count = 0; 620 - profile->secmark = NULL; 616 + kfree(rules->secmark[i].label); 617 + kfree(rules->secmark); 618 + rules->secmark_count = 0; 619 + rules->secmark = NULL; 621 620 } 622 621 623 622 e->pos = pos; ··· 635 634 u32 tmp = 0; 636 635 if (!unpack_u32(e, &tmp, NULL)) 637 636 goto fail; 638 - profile->rlimits.mask = tmp; 637 + profile->rules.rlimits.mask = tmp; 639 638 640 639 if (unpack_array(e, NULL, &size) != TRI_TRUE || 641 640 size > RLIM_NLIMITS) ··· 645 644 int a = aa_map_resource(i); 646 645 if (!unpack_u64(e, &tmp2, NULL)) 647 646 goto fail; 648 - profile->rlimits.limits[a].rlim_max = tmp2; 647 + profile->rules.rlimits.limits[a].rlim_max = tmp2; 649 648 } 650 649 if (!unpack_nameX(e, AA_ARRAYEND, NULL)) 651 650 goto fail; ··· 817 816 */ 818 817 static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) 819 818 { 819 + struct aa_ruleset *rules; 820 820 struct aa_profile *profile = NULL; 821 821 const char *tmpname, *tmpns = NULL, *name = NULL; 822 822 const char *info = "failed to unpack profile"; ··· 852 850 profile = aa_alloc_profile(name, NULL, GFP_KERNEL); 853 851 if (!profile) 854 852 return ERR_PTR(-ENOMEM); 853 + rules = &profile->rules; 855 854 856 855 /* profile renaming is optional */ 857 856 (void) unpack_str(e, &profile->rename, "rename"); 858 857 859 858 /* attachment string is optional */ 860 - (void) unpack_str(e, &profile->attach, "attach"); 859 + (void) unpack_str(e, &profile->attach.xmatch_str, "attach"); 861 860 862 861 /* xmatch is optional and may be NULL */ 863 - error = unpack_pdb(e, &profile->xmatch, false, false, &info); 864 - if (error) 862 + error = unpack_pdb(e, &profile->attach.xmatch, false, false, &info); 863 + if (error) { 864 + info = "bad xmatch"; 865 865 goto fail; 866 + } 866 867 867 868 /* neither xmatch_len not xmatch_perms are optional if xmatch is set */ 868 - if (profile->xmatch.dfa) { 869 + if (profile->attach.xmatch.dfa) { 869 870 if (!unpack_u32(e, &tmp, NULL)) { 870 871 info = "missing xmatch len"; 871 872 goto fail; 872 873 } 873 - profile->xmatch_len = tmp; 874 - profile->xmatch.start[AA_CLASS_XMATCH] = DFA_START; 875 - if (aa_compat_map_xmatch(&profile->xmatch)) { 874 + profile->attach.xmatch_len = tmp; 875 + profile->attach.xmatch.start[AA_CLASS_XMATCH] = DFA_START; 876 + if (aa_compat_map_xmatch(&profile->attach.xmatch)) { 876 877 info = "failed to convert xmatch permission table"; 877 878 goto fail; 878 879 } ··· 931 926 profile->path_flags = PATH_MEDIATE_DELETED; 932 927 933 928 info = "failed to unpack profile capabilities"; 934 - if (!unpack_u32(e, &(profile->caps.allow.cap[0]), NULL)) 929 + if (!unpack_u32(e, &(rules->caps.allow.cap[0]), NULL)) 935 930 goto fail; 936 - if (!unpack_u32(e, &(profile->caps.audit.cap[0]), NULL)) 931 + if (!unpack_u32(e, &(rules->caps.audit.cap[0]), NULL)) 937 932 goto fail; 938 - if (!unpack_u32(e, &(profile->caps.quiet.cap[0]), NULL)) 933 + if (!unpack_u32(e, &(rules->caps.quiet.cap[0]), NULL)) 939 934 goto fail; 940 935 if (!unpack_u32(e, &tmpcap.cap[0], NULL)) 941 936 goto fail; ··· 943 938 info = "failed to unpack upper profile capabilities"; 944 939 if (unpack_nameX(e, AA_STRUCT, "caps64")) { 945 940 /* optional upper half of 64 bit caps */ 946 - if (!unpack_u32(e, &(profile->caps.allow.cap[1]), NULL)) 941 + if (!unpack_u32(e, &(rules->caps.allow.cap[1]), NULL)) 947 942 goto fail; 948 - if (!unpack_u32(e, &(profile->caps.audit.cap[1]), NULL)) 943 + if (!unpack_u32(e, &(rules->caps.audit.cap[1]), NULL)) 949 944 goto fail; 950 - if (!unpack_u32(e, &(profile->caps.quiet.cap[1]), NULL)) 945 + if (!unpack_u32(e, &(rules->caps.quiet.cap[1]), NULL)) 951 946 goto fail; 952 947 if (!unpack_u32(e, &(tmpcap.cap[1]), NULL)) 953 948 goto fail; ··· 958 953 info = "failed to unpack extended profile capabilities"; 959 954 if (unpack_nameX(e, AA_STRUCT, "capsx")) { 960 955 /* optional extended caps mediation mask */ 961 - if (!unpack_u32(e, &(profile->caps.extended.cap[0]), NULL)) 956 + if (!unpack_u32(e, &(rules->caps.extended.cap[0]), NULL)) 962 957 goto fail; 963 - if (!unpack_u32(e, &(profile->caps.extended.cap[1]), NULL)) 958 + if (!unpack_u32(e, &(rules->caps.extended.cap[1]), NULL)) 964 959 goto fail; 965 960 if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 966 961 goto fail; ··· 984 979 if (unpack_nameX(e, AA_STRUCT, "policydb")) { 985 980 /* generic policy dfa - optional and may be NULL */ 986 981 info = "failed to unpack policydb"; 987 - error = unpack_pdb(e, &profile->policy, true, false, &info); 982 + error = unpack_pdb(e, &rules->policy, true, false, 983 + &info); 988 984 if (error) 989 985 goto fail; 990 986 /* Fixup: drop when we get rid of start array */ 991 - if (aa_dfa_next(profile->policy.dfa, profile->policy.start[0], 987 + if (aa_dfa_next(rules->policy.dfa, rules->policy.start[0], 992 988 AA_CLASS_FILE)) 993 - profile->policy.start[AA_CLASS_FILE] = 994 - aa_dfa_next(profile->policy.dfa, 995 - profile->policy.start[0], 989 + rules->policy.start[AA_CLASS_FILE] = 990 + aa_dfa_next(rules->policy.dfa, 991 + rules->policy.start[0], 996 992 AA_CLASS_FILE); 997 993 if (!unpack_nameX(e, AA_STRUCTEND, NULL)) 998 994 goto fail; 999 - if (aa_compat_map_policy(&profile->policy, e->version)) { 995 + if (aa_compat_map_policy(&rules->policy, e->version)) { 1000 996 info = "failed to remap policydb permission table"; 1001 997 goto fail; 1002 998 } 1003 999 } else 1004 - profile->policy.dfa = aa_get_dfa(nulldfa); 1000 + rules->policy.dfa = aa_get_dfa(nulldfa); 1005 1001 1006 1002 /* get file rules */ 1007 - error = unpack_pdb(e, &profile->file, false, true, &info); 1003 + error = unpack_pdb(e, &rules->file, false, true, &info); 1008 1004 if (error) { 1009 1005 goto fail; 1010 - } else if (profile->file.dfa) { 1011 - if (aa_compat_map_file(&profile->file)) { 1006 + } else if (rules->file.dfa) { 1007 + if (aa_compat_map_file(&rules->file)) { 1012 1008 info = "failed to remap file permission table"; 1013 1009 goto fail; 1014 1010 } 1015 - } else if (profile->policy.dfa && 1016 - profile->policy.start[AA_CLASS_FILE]) { 1017 - profile->file.dfa = aa_get_dfa(profile->policy.dfa); 1018 - profile->file.start[AA_CLASS_FILE] = profile->policy.start[AA_CLASS_FILE]; 1011 + } else if (rules->policy.dfa && 1012 + rules->policy.start[AA_CLASS_FILE]) { 1013 + rules->file.dfa = aa_get_dfa(rules->policy.dfa); 1014 + rules->file.start[AA_CLASS_FILE] = rules->policy.start[AA_CLASS_FILE]; 1019 1015 } else 1020 - profile->file.dfa = aa_get_dfa(nulldfa); 1016 + rules->file.dfa = aa_get_dfa(nulldfa); 1021 1017 1022 1018 if (unpack_nameX(e, AA_STRUCT, "data")) { 1023 1019 info = "out of memory"; ··· 1208 1202 */ 1209 1203 static int verify_profile(struct aa_profile *profile) 1210 1204 { 1211 - if ((profile->file.dfa && 1212 - !verify_dfa_xindex(profile->file.dfa, 1213 - profile->file.trans.size)) || 1214 - (profile->policy.dfa && 1215 - !verify_dfa_xindex(profile->policy.dfa, 1216 - profile->policy.trans.size))) { 1205 + if ((profile->rules.file.dfa && 1206 + !verify_dfa_xindex(profile->rules.file.dfa, 1207 + profile->rules.file.trans.size)) || 1208 + (profile->rules.policy.dfa && 1209 + !verify_dfa_xindex(profile->rules.policy.dfa, 1210 + profile->rules.policy.trans.size))) { 1217 1211 audit_iface(profile, NULL, NULL, 1218 1212 "Unpack: Invalid named transition", NULL, -EPROTO); 1219 1213 return -EPROTO; 1220 1214 } 1221 1215 1222 - if (!verify_perms(&profile->file)) { 1216 + if (!verify_perms(&profile->rules.file)) { 1223 1217 audit_iface(profile, NULL, NULL, 1224 1218 "Unpack: Invalid perm index", NULL, -EPROTO); 1225 1219 return -EPROTO; 1226 1220 } 1227 - if (!verify_perms(&profile->policy)) { 1221 + if (!verify_perms(&profile->rules.policy)) { 1228 1222 audit_iface(profile, NULL, NULL, 1229 1223 "Unpack: Invalid perm index", NULL, -EPROTO); 1230 1224 return -EPROTO; 1231 1225 } 1232 - if (!verify_perms(&profile->xmatch)) { 1226 + if (!verify_perms(&profile->attach.xmatch)) { 1233 1227 audit_iface(profile, NULL, NULL, 1234 1228 "Unpack: Invalid perm index", NULL, -EPROTO); 1235 1229 return -EPROTO;
+8 -7
security/apparmor/resource.c
··· 82 82 static int profile_setrlimit(struct aa_profile *profile, unsigned int resource, 83 83 struct rlimit *new_rlim) 84 84 { 85 + struct aa_ruleset *rules = &profile->rules; 85 86 int e = 0; 86 87 87 - if (profile->rlimits.mask & (1 << resource) && new_rlim->rlim_max > 88 - profile->rlimits.limits[resource].rlim_max) 88 + if (rules->rlimits.mask & (1 << resource) && new_rlim->rlim_max > 89 + rules->rlimits.limits[resource].rlim_max) 89 90 e = -EACCES; 90 91 return audit_resource(profile, resource, new_rlim->rlim_max, NULL, NULL, 91 92 e); ··· 154 153 * to the lesser of the tasks hard limit and the init tasks soft limit 155 154 */ 156 155 label_for_each_confined(i, old_l, old) { 157 - if (old->rlimits.mask) { 156 + if (old->rules.rlimits.mask) { 158 157 int j; 159 158 160 159 for (j = 0, mask = 1; j < RLIM_NLIMITS; j++, 161 160 mask <<= 1) { 162 - if (old->rlimits.mask & mask) { 161 + if (old->rules.rlimits.mask & mask) { 163 162 rlim = current->signal->rlim + j; 164 163 initrlim = init_task.signal->rlim + j; 165 164 rlim->rlim_cur = min(rlim->rlim_max, ··· 173 172 label_for_each_confined(i, new_l, new) { 174 173 int j; 175 174 176 - if (!new->rlimits.mask) 175 + if (!new->rules.rlimits.mask) 177 176 continue; 178 177 for (j = 0, mask = 1; j < RLIM_NLIMITS; j++, mask <<= 1) { 179 - if (!(new->rlimits.mask & mask)) 178 + if (!(new->rules.rlimits.mask & mask)) 180 179 continue; 181 180 182 181 rlim = current->signal->rlim + j; 183 182 rlim->rlim_max = min(rlim->rlim_max, 184 - new->rlimits.limits[j].rlim_max); 183 + new->rules.rlimits.limits[j].rlim_max); 185 184 /* soft limit should not exceed hard limit */ 186 185 rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max); 187 186 }
+5 -5
security/apparmor/task.c
··· 223 223 FLAGS_NONE, GFP_ATOMIC); 224 224 } 225 225 226 - /* assumes check for PROFILE_MEDIATES is already done */ 226 + /* assumes check for RULE_MEDIATES is already done */ 227 227 /* TODO: conditionals */ 228 228 static int profile_ptrace_perm(struct aa_profile *profile, 229 229 struct aa_label *peer, u32 request, ··· 232 232 struct aa_perms perms = { }; 233 233 234 234 aad(sa)->peer = peer; 235 - aa_profile_match_label(profile, peer, AA_CLASS_PTRACE, request, 236 - &perms); 235 + aa_profile_match_label(profile, &profile->rules, peer, 236 + AA_CLASS_PTRACE, request, &perms); 237 237 aa_apply_modes_to_perms(profile, &perms); 238 238 return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb); 239 239 } ··· 243 243 struct common_audit_data *sa) 244 244 { 245 245 if (profile_unconfined(tracee) || unconfined(tracer) || 246 - !PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE)) 246 + !RULE_MEDIATES(&tracee->rules, AA_CLASS_PTRACE)) 247 247 return 0; 248 248 249 249 return profile_ptrace_perm(tracee, tracer, request, sa); ··· 256 256 if (profile_unconfined(tracer)) 257 257 return 0; 258 258 259 - if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE)) 259 + if (RULE_MEDIATES(&tracer->rules, AA_CLASS_PTRACE)) 260 260 return profile_ptrace_perm(tracer, tracee, request, sa); 261 261 262 262 /* profile uses the old style capability check for ptrace */