1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * AppArmor security module 4 * 5 * This file contains AppArmor policy attachment and domain transitions 6 * 7 * Copyright (C) 2002-2008 Novell/SUSE 8 * Copyright 2009-2010 Canonical Ltd. 9 */ 10 11 #include <linux/errno.h> 12 #include <linux/fdtable.h> 13 #include <linux/fs.h> 14 #include <linux/file.h> 15 #include <linux/mount.h> 16 #include <linux/syscalls.h> 17 #include <linux/personality.h> 18 #include <linux/xattr.h> 19 #include <linux/user_namespace.h> 20 21 #include "include/audit.h" 22 #include "include/apparmorfs.h" 23 #include "include/cred.h" 24 #include "include/domain.h" 25 #include "include/file.h" 26 #include "include/ipc.h" 27 #include "include/match.h" 28 #include "include/path.h" 29 #include "include/policy.h" 30 #include "include/policy_ns.h" 31 32 /** 33 * may_change_ptraced_domain - check if can change profile on ptraced task 34 * @cred: cred of task changing domain 35 * @to_label: profile to change to (NOT NULL) 36 * @info: message if there is an error 37 * 38 * Check if current is ptraced and if so if the tracing task is allowed 39 * to trace the new domain 40 * 41 * Returns: %0 or error if change not allowed 42 */ 43 static int may_change_ptraced_domain(const struct cred *to_cred, 44 struct aa_label *to_label, 45 const char **info) 46 { 47 struct task_struct *tracer; 48 struct aa_label *tracerl = NULL; 49 const struct cred *tracer_cred = NULL; 50 51 int error = 0; 52 53 rcu_read_lock(); 54 tracer = ptrace_parent(current); 55 if (tracer) { 56 /* released below */ 57 tracerl = aa_get_task_label(tracer); 58 tracer_cred = get_task_cred(tracer); 59 } 60 /* not ptraced */ 61 if (!tracer || unconfined(tracerl)) 62 goto out; 63 64 error = aa_may_ptrace(tracer_cred, tracerl, to_cred, to_label, 65 PTRACE_MODE_ATTACH); 66 67 out: 68 rcu_read_unlock(); 69 aa_put_label(tracerl); 70 put_cred(tracer_cred); 71 72 if (error) 73 *info = "ptrace prevents transition"; 74 return error; 75 } 76 77 /**** TODO: dedup to aa_label_match - needs perm and dfa, merging 78 * specifically this is an exact copy of aa_label_match except 79 * aa_compute_perms is replaced with aa_compute_fperms 80 * and policy.dfa with file.dfa 81 ****/ 82 /* match a profile and its associated ns component if needed 83 * Assumes visibility test has already been done. 84 * If a subns profile is not to be matched should be prescreened with 85 * visibility test. 86 */ 87 static inline aa_state_t match_component(struct aa_profile *profile, 88 struct aa_profile *tp, 89 bool stack, aa_state_t state) 90 { 91 struct aa_ruleset *rules = list_first_entry(&profile->rules, 92 typeof(*rules), list); 93 const char *ns_name; 94 95 if (stack) 96 state = aa_dfa_match(rules->file.dfa, state, "&"); 97 if (profile->ns == tp->ns) 98 return aa_dfa_match(rules->file.dfa, state, tp->base.hname); 99 100 /* try matching with namespace name and then profile */ 101 ns_name = aa_ns_name(profile->ns, tp->ns, true); 102 state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); 103 state = aa_dfa_match(rules->file.dfa, state, ns_name); 104 state = aa_dfa_match_len(rules->file.dfa, state, ":", 1); 105 return aa_dfa_match(rules->file.dfa, state, tp->base.hname); 106 } 107 108 /** 109 * label_compound_match - find perms for full compound label 110 * @profile: profile to find perms for 111 * @label: label to check access permissions for 112 * @stack: whether this is a stacking request 113 * @state: state to start match in 114 * @subns: whether to do permission checks on components in a subns 115 * @request: permissions to request 116 * @perms: perms struct to set 117 * 118 * Returns: 0 on success else ERROR 119 * 120 * For the label A//&B//&C this does the perm match for A//&B//&C 121 * @perms should be preinitialized with allperms OR a previous permission 122 * check to be stacked. 123 */ 124 static int label_compound_match(struct aa_profile *profile, 125 struct aa_label *label, bool stack, 126 aa_state_t state, bool subns, u32 request, 127 struct aa_perms *perms) 128 { 129 struct aa_ruleset *rules = list_first_entry(&profile->rules, 130 typeof(*rules), list); 131 struct aa_profile *tp; 132 struct label_it i; 133 struct path_cond cond = { }; 134 135 /* find first subcomponent that is visible */ 136 label_for_each(i, label, tp) { 137 if (!aa_ns_visible(profile->ns, tp->ns, subns)) 138 continue; 139 state = match_component(profile, tp, stack, state); 140 if (!state) 141 goto fail; 142 goto next; 143 } 144 145 /* no component visible */ 146 *perms = allperms; 147 return 0; 148 149 next: 150 label_for_each_cont(i, label, tp) { 151 if (!aa_ns_visible(profile->ns, tp->ns, subns)) 152 continue; 153 state = aa_dfa_match(rules->file.dfa, state, "//&"); 154 state = match_component(profile, tp, false, state); 155 if (!state) 156 goto fail; 157 } 158 *perms = *(aa_lookup_fperms(&(rules->file), state, &cond)); 159 aa_apply_modes_to_perms(profile, perms); 160 if ((perms->allow & request) != request) 161 return -EACCES; 162 163 return 0; 164 165 fail: 166 *perms = nullperms; 167 return -EACCES; 168 } 169 170 /** 171 * label_components_match - find perms for all subcomponents of a label 172 * @profile: profile to find perms for 173 * @label: label to check access permissions for 174 * @stack: whether this is a stacking request 175 * @start: state to start match in 176 * @subns: whether to do permission checks on components in a subns 177 * @request: permissions to request 178 * @perms: an initialized perms struct to add accumulation to 179 * 180 * Returns: 0 on success else ERROR 181 * 182 * For the label A//&B//&C this does the perm match for each of A and B and C 183 * @perms should be preinitialized with allperms OR a previous permission 184 * check to be stacked. 185 */ 186 static int label_components_match(struct aa_profile *profile, 187 struct aa_label *label, bool stack, 188 aa_state_t start, bool subns, u32 request, 189 struct aa_perms *perms) 190 { 191 struct aa_ruleset *rules = list_first_entry(&profile->rules, 192 typeof(*rules), list); 193 struct aa_profile *tp; 194 struct label_it i; 195 struct aa_perms tmp; 196 struct path_cond cond = { }; 197 aa_state_t state = 0; 198 199 /* find first subcomponent to test */ 200 label_for_each(i, label, tp) { 201 if (!aa_ns_visible(profile->ns, tp->ns, subns)) 202 continue; 203 state = match_component(profile, tp, stack, start); 204 if (!state) 205 goto fail; 206 goto next; 207 } 208 209 /* no subcomponents visible - no change in perms */ 210 return 0; 211 212 next: 213 tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); 214 aa_apply_modes_to_perms(profile, &tmp); 215 aa_perms_accum(perms, &tmp); 216 label_for_each_cont(i, label, tp) { 217 if (!aa_ns_visible(profile->ns, tp->ns, subns)) 218 continue; 219 state = match_component(profile, tp, stack, start); 220 if (!state) 221 goto fail; 222 tmp = *(aa_lookup_fperms(&(rules->file), state, &cond)); 223 aa_apply_modes_to_perms(profile, &tmp); 224 aa_perms_accum(perms, &tmp); 225 } 226 227 if ((perms->allow & request) != request) 228 return -EACCES; 229 230 return 0; 231 232 fail: 233 *perms = nullperms; 234 return -EACCES; 235 } 236 237 /** 238 * label_match - do a multi-component label match 239 * @profile: profile to match against (NOT NULL) 240 * @label: label to match (NOT NULL) 241 * @stack: whether this is a stacking request 242 * @state: state to start in 243 * @subns: whether to match subns components 244 * @request: permission request 245 * @perms: Returns computed perms (NOT NULL) 246 * 247 * Returns: the state the match finished in, may be the none matching state 248 */ 249 static int label_match(struct aa_profile *profile, struct aa_label *label, 250 bool stack, aa_state_t state, bool subns, u32 request, 251 struct aa_perms *perms) 252 { 253 int error; 254 255 *perms = nullperms; 256 error = label_compound_match(profile, label, stack, state, subns, 257 request, perms); 258 if (!error) 259 return error; 260 261 *perms = allperms; 262 return label_components_match(profile, label, stack, state, subns, 263 request, perms); 264 } 265 266 /******* end TODO: dedup *****/ 267 268 /** 269 * change_profile_perms - find permissions for change_profile 270 * @profile: the current profile (NOT NULL) 271 * @target: label to transition to (NOT NULL) 272 * @stack: whether this is a stacking request 273 * @request: requested perms 274 * @start: state to start matching in 275 * 276 * 277 * Returns: permission set 278 * 279 * currently only matches full label A//&B//&C or individual components A, B, C 280 * not arbitrary combinations. Eg. A//&B, C 281 */ 282 static int change_profile_perms(struct aa_profile *profile, 283 struct aa_label *target, bool stack, 284 u32 request, aa_state_t start, 285 struct aa_perms *perms) 286 { 287 if (profile_unconfined(profile)) { 288 perms->allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC; 289 perms->audit = perms->quiet = perms->kill = 0; 290 return 0; 291 } 292 293 /* TODO: add profile in ns screening */ 294 return label_match(profile, target, stack, start, true, request, perms); 295 } 296 297 /** 298 * aa_xattrs_match - check whether a file matches the xattrs defined in profile 299 * @bprm: binprm struct for the process to validate 300 * @profile: profile to match against (NOT NULL) 301 * @state: state to start match in 302 * 303 * Returns: number of extended attributes that matched, or < 0 on error 304 */ 305 static int aa_xattrs_match(const struct linux_binprm *bprm, 306 struct aa_profile *profile, aa_state_t state) 307 { 308 int i; 309 struct dentry *d; 310 char *value = NULL; 311 struct aa_attachment *attach = &profile->attach; 312 int size, value_size = 0, ret = attach->xattr_count; 313 314 if (!bprm || !attach->xattr_count) 315 return 0; 316 might_sleep(); 317 318 /* transition from exec match to xattr set */ 319 state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); 320 d = bprm->file->f_path.dentry; 321 322 for (i = 0; i < attach->xattr_count; i++) { 323 size = vfs_getxattr_alloc(&nop_mnt_idmap, d, attach->xattrs[i], 324 &value, value_size, GFP_KERNEL); 325 if (size >= 0) { 326 u32 index, perm; 327 328 /* 329 * Check the xattr presence before value. This ensure 330 * that not present xattr can be distinguished from a 0 331 * length value or rule that matches any value 332 */ 333 state = aa_dfa_null_transition(attach->xmatch.dfa, 334 state); 335 /* Check xattr value */ 336 state = aa_dfa_match_len(attach->xmatch.dfa, state, 337 value, size); 338 index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; 339 perm = attach->xmatch.perms[index].allow; 340 if (!(perm & MAY_EXEC)) { 341 ret = -EINVAL; 342 goto out; 343 } 344 } 345 /* transition to next element */ 346 state = aa_dfa_outofband_transition(attach->xmatch.dfa, state); 347 if (size < 0) { 348 /* 349 * No xattr match, so verify if transition to 350 * next element was valid. IFF so the xattr 351 * was optional. 352 */ 353 if (!state) { 354 ret = -EINVAL; 355 goto out; 356 } 357 /* don't count missing optional xattr as matched */ 358 ret--; 359 } 360 } 361 362 out: 363 kfree(value); 364 return ret; 365 } 366 367 /** 368 * find_attach - do attachment search for unconfined processes 369 * @bprm - binprm structure of transitioning task 370 * @ns: the current namespace (NOT NULL) 371 * @head - profile list to walk (NOT NULL) 372 * @name - to match against (NOT NULL) 373 * @info - info message if there was an error (NOT NULL) 374 * 375 * Do a linear search on the profiles in the list. There is a matching 376 * preference where an exact match is preferred over a name which uses 377 * expressions to match, and matching expressions with the greatest 378 * xmatch_len are preferred. 379 * 380 * Requires: @head not be shared or have appropriate locks held 381 * 382 * Returns: label or NULL if no match found 383 */ 384 static struct aa_label *find_attach(const struct linux_binprm *bprm, 385 struct aa_ns *ns, struct list_head *head, 386 const char *name, const char **info) 387 { 388 int candidate_len = 0, candidate_xattrs = 0; 389 bool conflict = false; 390 struct aa_profile *profile, *candidate = NULL; 391 392 AA_BUG(!name); 393 AA_BUG(!head); 394 395 rcu_read_lock(); 396 restart: 397 list_for_each_entry_rcu(profile, head, base.list) { 398 struct aa_attachment *attach = &profile->attach; 399 400 if (profile->label.flags & FLAG_NULL && 401 &profile->label == ns_unconfined(profile->ns)) 402 continue; 403 404 /* Find the "best" matching profile. Profiles must 405 * match the path and extended attributes (if any) 406 * associated with the file. A more specific path 407 * match will be preferred over a less specific one, 408 * and a match with more matching extended attributes 409 * will be preferred over one with fewer. If the best 410 * match has both the same level of path specificity 411 * and the same number of matching extended attributes 412 * as another profile, signal a conflict and refuse to 413 * match. 414 */ 415 if (attach->xmatch.dfa) { 416 unsigned int count; 417 aa_state_t state; 418 u32 index, perm; 419 420 state = aa_dfa_leftmatch(attach->xmatch.dfa, 421 attach->xmatch.start[AA_CLASS_XMATCH], 422 name, &count); 423 index = ACCEPT_TABLE(attach->xmatch.dfa)[state]; 424 perm = attach->xmatch.perms[index].allow; 425 /* any accepting state means a valid match. */ 426 if (perm & MAY_EXEC) { 427 int ret = 0; 428 429 if (count < candidate_len) 430 continue; 431 432 if (bprm && attach->xattr_count) { 433 long rev = READ_ONCE(ns->revision); 434 435 if (!aa_get_profile_not0(profile)) 436 goto restart; 437 rcu_read_unlock(); 438 ret = aa_xattrs_match(bprm, profile, 439 state); 440 rcu_read_lock(); 441 aa_put_profile(profile); 442 if (rev != 443 READ_ONCE(ns->revision)) 444 /* policy changed */ 445 goto restart; 446 /* 447 * Fail matching if the xattrs don't 448 * match 449 */ 450 if (ret < 0) 451 continue; 452 } 453 /* 454 * TODO: allow for more flexible best match 455 * 456 * The new match isn't more specific 457 * than the current best match 458 */ 459 if (count == candidate_len && 460 ret <= candidate_xattrs) { 461 /* Match is equivalent, so conflict */ 462 if (ret == candidate_xattrs) 463 conflict = true; 464 continue; 465 } 466 467 /* Either the same length with more matching 468 * xattrs, or a longer match 469 */ 470 candidate = profile; 471 candidate_len = max(count, attach->xmatch_len); 472 candidate_xattrs = ret; 473 conflict = false; 474 } 475 } else if (!strcmp(profile->base.name, name)) { 476 /* 477 * old exact non-re match, without conditionals such 478 * as xattrs. no more searching required 479 */ 480 candidate = profile; 481 goto out; 482 } 483 } 484 485 if (!candidate || conflict) { 486 if (conflict) 487 *info = "conflicting profile attachments"; 488 rcu_read_unlock(); 489 return NULL; 490 } 491 492 out: 493 candidate = aa_get_newest_profile(candidate); 494 rcu_read_unlock(); 495 496 return &candidate->label; 497 } 498 499 static const char *next_name(int xtype, const char *name) 500 { 501 return NULL; 502 } 503 504 /** 505 * x_table_lookup - lookup an x transition name via transition table 506 * @profile: current profile (NOT NULL) 507 * @xindex: index into x transition table 508 * @name: returns: name tested to find label (NOT NULL) 509 * 510 * Returns: refcounted label, or NULL on failure (MAYBE NULL) 511 */ 512 struct aa_label *x_table_lookup(struct aa_profile *profile, u32 xindex, 513 const char **name) 514 { 515 struct aa_ruleset *rules = list_first_entry(&profile->rules, 516 typeof(*rules), list); 517 struct aa_label *label = NULL; 518 u32 xtype = xindex & AA_X_TYPE_MASK; 519 int index = xindex & AA_X_INDEX_MASK; 520 521 AA_BUG(!name); 522 523 /* index is guaranteed to be in range, validated at load time */ 524 /* TODO: move lookup parsing to unpack time so this is a straight 525 * index into the resultant label 526 */ 527 for (*name = rules->file.trans.table[index]; !label && *name; 528 *name = next_name(xtype, *name)) { 529 if (xindex & AA_X_CHILD) { 530 struct aa_profile *new_profile; 531 /* release by caller */ 532 new_profile = aa_find_child(profile, *name); 533 if (new_profile) 534 label = &new_profile->label; 535 continue; 536 } 537 label = aa_label_parse(&profile->label, *name, GFP_KERNEL, 538 true, false); 539 if (IS_ERR(label)) 540 label = NULL; 541 } 542 543 /* released by caller */ 544 545 return label; 546 } 547 548 /** 549 * x_to_label - get target label for a given xindex 550 * @profile: current profile (NOT NULL) 551 * @bprm: binprm structure of transitioning task 552 * @name: name to lookup (NOT NULL) 553 * @xindex: index into x transition table 554 * @lookupname: returns: name used in lookup if one was specified (NOT NULL) 555 * 556 * find label for a transition index 557 * 558 * Returns: refcounted label or NULL if not found available 559 */ 560 static struct aa_label *x_to_label(struct aa_profile *profile, 561 const struct linux_binprm *bprm, 562 const char *name, u32 xindex, 563 const char **lookupname, 564 const char **info) 565 { 566 struct aa_ruleset *rules = list_first_entry(&profile->rules, 567 typeof(*rules), list); 568 struct aa_label *new = NULL; 569 struct aa_ns *ns = profile->ns; 570 u32 xtype = xindex & AA_X_TYPE_MASK; 571 const char *stack = NULL; 572 573 switch (xtype) { 574 case AA_X_NONE: 575 /* fail exec unless ix || ux fallback - handled by caller */ 576 *lookupname = NULL; 577 break; 578 case AA_X_TABLE: 579 /* TODO: fix when perm mapping done at unload */ 580 stack = rules->file.trans.table[xindex & AA_X_INDEX_MASK]; 581 if (*stack != '&') { 582 /* released by caller */ 583 new = x_table_lookup(profile, xindex, lookupname); 584 stack = NULL; 585 break; 586 } 587 fallthrough; /* to X_NAME */ 588 case AA_X_NAME: 589 if (xindex & AA_X_CHILD) 590 /* released by caller */ 591 new = find_attach(bprm, ns, &profile->base.profiles, 592 name, info); 593 else 594 /* released by caller */ 595 new = find_attach(bprm, ns, &ns->base.profiles, 596 name, info); 597 *lookupname = name; 598 break; 599 } 600 601 if (!new) { 602 if (xindex & AA_X_INHERIT) { 603 /* (p|c|n)ix - don't change profile but do 604 * use the newest version 605 */ 606 *info = "ix fallback"; 607 /* no profile && no error */ 608 new = aa_get_newest_label(&profile->label); 609 } else if (xindex & AA_X_UNCONFINED) { 610 new = aa_get_newest_label(ns_unconfined(profile->ns)); 611 *info = "ux fallback"; 612 } 613 } 614 615 if (new && stack) { 616 /* base the stack on post domain transition */ 617 struct aa_label *base = new; 618 619 new = aa_label_parse(base, stack, GFP_KERNEL, true, false); 620 if (IS_ERR(new)) 621 new = NULL; 622 aa_put_label(base); 623 } 624 625 /* released by caller */ 626 return new; 627 } 628 629 static struct aa_label *profile_transition(const struct cred *subj_cred, 630 struct aa_profile *profile, 631 const struct linux_binprm *bprm, 632 char *buffer, struct path_cond *cond, 633 bool *secure_exec) 634 { 635 struct aa_ruleset *rules = list_first_entry(&profile->rules, 636 typeof(*rules), list); 637 struct aa_label *new = NULL; 638 const char *info = NULL, *name = NULL, *target = NULL; 639 aa_state_t state = rules->file.start[AA_CLASS_FILE]; 640 struct aa_perms perms = {}; 641 bool nonewprivs = false; 642 int error = 0; 643 644 AA_BUG(!profile); 645 AA_BUG(!bprm); 646 AA_BUG(!buffer); 647 648 error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer, 649 &name, &info, profile->disconnected); 650 if (error) { 651 if (profile_unconfined(profile) || 652 (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) { 653 AA_DEBUG("name lookup ix on error"); 654 error = 0; 655 new = aa_get_newest_label(&profile->label); 656 } 657 name = bprm->filename; 658 goto audit; 659 } 660 661 if (profile_unconfined(profile)) { 662 new = find_attach(bprm, profile->ns, 663 &profile->ns->base.profiles, name, &info); 664 if (new) { 665 AA_DEBUG("unconfined attached to new label"); 666 return new; 667 } 668 AA_DEBUG("unconfined exec no attachment"); 669 return aa_get_newest_label(&profile->label); 670 } 671 672 /* find exec permissions for name */ 673 state = aa_str_perms(&(rules->file), state, name, cond, &perms); 674 if (perms.allow & MAY_EXEC) { 675 /* exec permission determine how to transition */ 676 new = x_to_label(profile, bprm, name, perms.xindex, &target, 677 &info); 678 if (new && new->proxy == profile->label.proxy && info) { 679 /* hack ix fallback - improve how this is detected */ 680 goto audit; 681 } else if (!new) { 682 error = -EACCES; 683 info = "profile transition not found"; 684 /* remove MAY_EXEC to audit as failure */ 685 perms.allow &= ~MAY_EXEC; 686 } 687 } else if (COMPLAIN_MODE(profile)) { 688 /* no exec permission - learning mode */ 689 struct aa_profile *new_profile = NULL; 690 691 new_profile = aa_new_learning_profile(profile, false, name, 692 GFP_KERNEL); 693 if (!new_profile) { 694 error = -ENOMEM; 695 info = "could not create null profile"; 696 } else { 697 error = -EACCES; 698 new = &new_profile->label; 699 } 700 perms.xindex |= AA_X_UNSAFE; 701 } else 702 /* fail exec */ 703 error = -EACCES; 704 705 if (!new) 706 goto audit; 707 708 709 if (!(perms.xindex & AA_X_UNSAFE)) { 710 if (DEBUG_ON) { 711 dbg_printk("apparmor: scrubbing environment variables" 712 " for %s profile=", name); 713 aa_label_printk(new, GFP_KERNEL); 714 dbg_printk("\n"); 715 } 716 *secure_exec = true; 717 } 718 719 audit: 720 aa_audit_file(subj_cred, profile, &perms, OP_EXEC, MAY_EXEC, name, 721 target, new, 722 cond->uid, info, error); 723 if (!new || nonewprivs) { 724 aa_put_label(new); 725 return ERR_PTR(error); 726 } 727 728 return new; 729 } 730 731 static int profile_onexec(const struct cred *subj_cred, 732 struct aa_profile *profile, struct aa_label *onexec, 733 bool stack, const struct linux_binprm *bprm, 734 char *buffer, struct path_cond *cond, 735 bool *secure_exec) 736 { 737 struct aa_ruleset *rules = list_first_entry(&profile->rules, 738 typeof(*rules), list); 739 aa_state_t state = rules->file.start[AA_CLASS_FILE]; 740 struct aa_perms perms = {}; 741 const char *xname = NULL, *info = "change_profile onexec"; 742 int error = -EACCES; 743 744 AA_BUG(!profile); 745 AA_BUG(!onexec); 746 AA_BUG(!bprm); 747 AA_BUG(!buffer); 748 749 if (profile_unconfined(profile)) { 750 /* change_profile on exec already granted */ 751 /* 752 * NOTE: Domain transitions from unconfined are allowed 753 * even when no_new_privs is set because this aways results 754 * in a further reduction of permissions. 755 */ 756 return 0; 757 } 758 759 error = aa_path_name(&bprm->file->f_path, profile->path_flags, buffer, 760 &xname, &info, profile->disconnected); 761 if (error) { 762 if (profile_unconfined(profile) || 763 (profile->label.flags & FLAG_IX_ON_NAME_ERROR)) { 764 AA_DEBUG("name lookup ix on error"); 765 error = 0; 766 } 767 xname = bprm->filename; 768 goto audit; 769 } 770 771 /* find exec permissions for name */ 772 state = aa_str_perms(&(rules->file), state, xname, cond, &perms); 773 if (!(perms.allow & AA_MAY_ONEXEC)) { 774 info = "no change_onexec valid for executable"; 775 goto audit; 776 } 777 /* test if this exec can be paired with change_profile onexec. 778 * onexec permission is linked to exec with a standard pairing 779 * exec\0change_profile 780 */ 781 state = aa_dfa_null_transition(rules->file.dfa, state); 782 error = change_profile_perms(profile, onexec, stack, AA_MAY_ONEXEC, 783 state, &perms); 784 if (error) { 785 perms.allow &= ~AA_MAY_ONEXEC; 786 goto audit; 787 } 788 789 if (!(perms.xindex & AA_X_UNSAFE)) { 790 if (DEBUG_ON) { 791 dbg_printk("apparmor: scrubbing environment " 792 "variables for %s label=", xname); 793 aa_label_printk(onexec, GFP_KERNEL); 794 dbg_printk("\n"); 795 } 796 *secure_exec = true; 797 } 798 799 audit: 800 return aa_audit_file(subj_cred, profile, &perms, OP_EXEC, 801 AA_MAY_ONEXEC, xname, 802 NULL, onexec, cond->uid, info, error); 803 } 804 805 /* ensure none ns domain transitions are correctly applied with onexec */ 806 807 static struct aa_label *handle_onexec(const struct cred *subj_cred, 808 struct aa_label *label, 809 struct aa_label *onexec, bool stack, 810 const struct linux_binprm *bprm, 811 char *buffer, struct path_cond *cond, 812 bool *unsafe) 813 { 814 struct aa_profile *profile; 815 struct aa_label *new; 816 int error; 817 818 AA_BUG(!label); 819 AA_BUG(!onexec); 820 AA_BUG(!bprm); 821 AA_BUG(!buffer); 822 823 if (!stack) { 824 error = fn_for_each_in_ns(label, profile, 825 profile_onexec(subj_cred, profile, onexec, stack, 826 bprm, buffer, cond, unsafe)); 827 if (error) 828 return ERR_PTR(error); 829 new = fn_label_build_in_ns(label, profile, GFP_KERNEL, 830 aa_get_newest_label(onexec), 831 profile_transition(subj_cred, profile, bprm, 832 buffer, 833 cond, unsafe)); 834 835 } else { 836 /* TODO: determine how much we want to loosen this */ 837 error = fn_for_each_in_ns(label, profile, 838 profile_onexec(subj_cred, profile, onexec, stack, bprm, 839 buffer, cond, unsafe)); 840 if (error) 841 return ERR_PTR(error); 842 new = fn_label_build_in_ns(label, profile, GFP_KERNEL, 843 aa_label_merge(&profile->label, onexec, 844 GFP_KERNEL), 845 profile_transition(subj_cred, profile, bprm, 846 buffer, 847 cond, unsafe)); 848 } 849 850 if (new) 851 return new; 852 853 /* TODO: get rid of GLOBAL_ROOT_UID */ 854 error = fn_for_each_in_ns(label, profile, 855 aa_audit_file(subj_cred, profile, &nullperms, 856 OP_CHANGE_ONEXEC, 857 AA_MAY_ONEXEC, bprm->filename, NULL, 858 onexec, GLOBAL_ROOT_UID, 859 "failed to build target label", -ENOMEM)); 860 return ERR_PTR(error); 861 } 862 863 /** 864 * apparmor_bprm_creds_for_exec - Update the new creds on the bprm struct 865 * @bprm: binprm for the exec (NOT NULL) 866 * 867 * Returns: %0 or error on failure 868 * 869 * TODO: once the other paths are done see if we can't refactor into a fn 870 */ 871 int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm) 872 { 873 struct aa_task_ctx *ctx; 874 struct aa_label *label, *new = NULL; 875 const struct cred *subj_cred; 876 struct aa_profile *profile; 877 char *buffer = NULL; 878 const char *info = NULL; 879 int error = 0; 880 bool unsafe = false; 881 vfsuid_t vfsuid = i_uid_into_vfsuid(file_mnt_idmap(bprm->file), 882 file_inode(bprm->file)); 883 struct path_cond cond = { 884 vfsuid_into_kuid(vfsuid), 885 file_inode(bprm->file)->i_mode 886 }; 887 888 subj_cred = current_cred(); 889 ctx = task_ctx(current); 890 AA_BUG(!cred_label(bprm->cred)); 891 AA_BUG(!ctx); 892 893 label = aa_get_newest_label(cred_label(bprm->cred)); 894 895 /* 896 * Detect no new privs being set, and store the label it 897 * occurred under. Ideally this would happen when nnp 898 * is set but there isn't a good way to do that yet. 899 * 900 * Testing for unconfined must be done before the subset test 901 */ 902 if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) && !unconfined(label) && 903 !ctx->nnp) 904 ctx->nnp = aa_get_label(label); 905 906 /* buffer freed below, name is pointer into buffer */ 907 buffer = aa_get_buffer(false); 908 if (!buffer) { 909 error = -ENOMEM; 910 goto done; 911 } 912 913 /* Test for onexec first as onexec override other x transitions. */ 914 if (ctx->onexec) 915 new = handle_onexec(subj_cred, label, ctx->onexec, ctx->token, 916 bprm, buffer, &cond, &unsafe); 917 else 918 new = fn_label_build(label, profile, GFP_KERNEL, 919 profile_transition(subj_cred, profile, bprm, 920 buffer, 921 &cond, &unsafe)); 922 923 AA_BUG(!new); 924 if (IS_ERR(new)) { 925 error = PTR_ERR(new); 926 goto done; 927 } else if (!new) { 928 error = -ENOMEM; 929 goto done; 930 } 931 932 /* Policy has specified a domain transitions. If no_new_privs and 933 * confined ensure the transition is to confinement that is subset 934 * of the confinement when the task entered no new privs. 935 * 936 * NOTE: Domain transitions from unconfined and to stacked 937 * subsets are allowed even when no_new_privs is set because this 938 * aways results in a further reduction of permissions. 939 */ 940 if ((bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) && 941 !unconfined(label) && 942 !aa_label_is_unconfined_subset(new, ctx->nnp)) { 943 error = -EPERM; 944 info = "no new privs"; 945 goto audit; 946 } 947 948 if (bprm->unsafe & LSM_UNSAFE_SHARE) { 949 /* FIXME: currently don't mediate shared state */ 950 ; 951 } 952 953 if (bprm->unsafe & (LSM_UNSAFE_PTRACE)) { 954 /* TODO: test needs to be profile of label to new */ 955 error = may_change_ptraced_domain(bprm->cred, new, &info); 956 if (error) 957 goto audit; 958 } 959 960 if (unsafe) { 961 if (DEBUG_ON) { 962 dbg_printk("scrubbing environment variables for %s " 963 "label=", bprm->filename); 964 aa_label_printk(new, GFP_KERNEL); 965 dbg_printk("\n"); 966 } 967 bprm->secureexec = 1; 968 } 969 970 if (label->proxy != new->proxy) { 971 /* when transitioning clear unsafe personality bits */ 972 if (DEBUG_ON) { 973 dbg_printk("apparmor: clearing unsafe personality " 974 "bits. %s label=", bprm->filename); 975 aa_label_printk(new, GFP_KERNEL); 976 dbg_printk("\n"); 977 } 978 bprm->per_clear |= PER_CLEAR_ON_SETID; 979 } 980 aa_put_label(cred_label(bprm->cred)); 981 /* transfer reference, released when cred is freed */ 982 set_cred_label(bprm->cred, new); 983 984 done: 985 aa_put_label(label); 986 aa_put_buffer(buffer); 987 988 return error; 989 990 audit: 991 error = fn_for_each(label, profile, 992 aa_audit_file(current_cred(), profile, &nullperms, 993 OP_EXEC, MAY_EXEC, 994 bprm->filename, NULL, new, 995 vfsuid_into_kuid(vfsuid), info, error)); 996 aa_put_label(new); 997 goto done; 998 } 999 1000 /* 1001 * Functions for self directed profile change 1002 */ 1003 1004 1005 /* helper fn for change_hat 1006 * 1007 * Returns: label for hat transition OR ERR_PTR. Does NOT return NULL 1008 */ 1009 static struct aa_label *build_change_hat(const struct cred *subj_cred, 1010 struct aa_profile *profile, 1011 const char *name, bool sibling) 1012 { 1013 struct aa_profile *root, *hat = NULL; 1014 const char *info = NULL; 1015 int error = 0; 1016 1017 if (sibling && PROFILE_IS_HAT(profile)) { 1018 root = aa_get_profile_rcu(&profile->parent); 1019 } else if (!sibling && !PROFILE_IS_HAT(profile)) { 1020 root = aa_get_profile(profile); 1021 } else { 1022 info = "conflicting target types"; 1023 error = -EPERM; 1024 goto audit; 1025 } 1026 1027 hat = aa_find_child(root, name); 1028 if (!hat) { 1029 error = -ENOENT; 1030 if (COMPLAIN_MODE(profile)) { 1031 hat = aa_new_learning_profile(profile, true, name, 1032 GFP_KERNEL); 1033 if (!hat) { 1034 info = "failed null profile create"; 1035 error = -ENOMEM; 1036 } 1037 } 1038 } 1039 aa_put_profile(root); 1040 1041 audit: 1042 aa_audit_file(subj_cred, profile, &nullperms, OP_CHANGE_HAT, 1043 AA_MAY_CHANGEHAT, 1044 name, hat ? hat->base.hname : NULL, 1045 hat ? &hat->label : NULL, GLOBAL_ROOT_UID, info, 1046 error); 1047 if (!hat || (error && error != -ENOENT)) 1048 return ERR_PTR(error); 1049 /* if hat && error - complain mode, already audited and we adjust for 1050 * complain mode allow by returning hat->label 1051 */ 1052 return &hat->label; 1053 } 1054 1055 /* helper fn for changing into a hat 1056 * 1057 * Returns: label for hat transition or ERR_PTR. Does not return NULL 1058 */ 1059 static struct aa_label *change_hat(const struct cred *subj_cred, 1060 struct aa_label *label, const char *hats[], 1061 int count, int flags) 1062 { 1063 struct aa_profile *profile, *root, *hat = NULL; 1064 struct aa_label *new; 1065 struct label_it it; 1066 bool sibling = false; 1067 const char *name, *info = NULL; 1068 int i, error; 1069 1070 AA_BUG(!label); 1071 AA_BUG(!hats); 1072 AA_BUG(count < 1); 1073 1074 if (PROFILE_IS_HAT(labels_profile(label))) 1075 sibling = true; 1076 1077 /*find first matching hat */ 1078 for (i = 0; i < count && !hat; i++) { 1079 name = hats[i]; 1080 label_for_each_in_ns(it, labels_ns(label), label, profile) { 1081 if (sibling && PROFILE_IS_HAT(profile)) { 1082 root = aa_get_profile_rcu(&profile->parent); 1083 } else if (!sibling && !PROFILE_IS_HAT(profile)) { 1084 root = aa_get_profile(profile); 1085 } else { /* conflicting change type */ 1086 info = "conflicting targets types"; 1087 error = -EPERM; 1088 goto fail; 1089 } 1090 hat = aa_find_child(root, name); 1091 aa_put_profile(root); 1092 if (!hat) { 1093 if (!COMPLAIN_MODE(profile)) 1094 goto outer_continue; 1095 /* complain mode succeed as if hat */ 1096 } else if (!PROFILE_IS_HAT(hat)) { 1097 info = "target not hat"; 1098 error = -EPERM; 1099 aa_put_profile(hat); 1100 goto fail; 1101 } 1102 aa_put_profile(hat); 1103 } 1104 /* found a hat for all profiles in ns */ 1105 goto build; 1106 outer_continue: 1107 ; 1108 } 1109 /* no hats that match, find appropriate error 1110 * 1111 * In complain mode audit of the failure is based off of the first 1112 * hat supplied. This is done due how userspace interacts with 1113 * change_hat. 1114 */ 1115 name = NULL; 1116 label_for_each_in_ns(it, labels_ns(label), label, profile) { 1117 if (!list_empty(&profile->base.profiles)) { 1118 info = "hat not found"; 1119 error = -ENOENT; 1120 goto fail; 1121 } 1122 } 1123 info = "no hats defined"; 1124 error = -ECHILD; 1125 1126 fail: 1127 label_for_each_in_ns(it, labels_ns(label), label, profile) { 1128 /* 1129 * no target as it has failed to be found or built 1130 * 1131 * change_hat uses probing and should not log failures 1132 * related to missing hats 1133 */ 1134 /* TODO: get rid of GLOBAL_ROOT_UID */ 1135 if (count > 1 || COMPLAIN_MODE(profile)) { 1136 aa_audit_file(subj_cred, profile, &nullperms, 1137 OP_CHANGE_HAT, 1138 AA_MAY_CHANGEHAT, name, NULL, NULL, 1139 GLOBAL_ROOT_UID, info, error); 1140 } 1141 } 1142 return ERR_PTR(error); 1143 1144 build: 1145 new = fn_label_build_in_ns(label, profile, GFP_KERNEL, 1146 build_change_hat(subj_cred, profile, name, 1147 sibling), 1148 aa_get_label(&profile->label)); 1149 if (!new) { 1150 info = "label build failed"; 1151 error = -ENOMEM; 1152 goto fail; 1153 } /* else if (IS_ERR) build_change_hat has logged error so return new */ 1154 1155 return new; 1156 } 1157 1158 /** 1159 * aa_change_hat - change hat to/from subprofile 1160 * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0) 1161 * @count: number of hat names in @hats 1162 * @token: magic value to validate the hat change 1163 * @flags: flags affecting behavior of the change 1164 * 1165 * Returns %0 on success, error otherwise. 1166 * 1167 * Change to the first profile specified in @hats that exists, and store 1168 * the @hat_magic in the current task context. If the count == 0 and the 1169 * @token matches that stored in the current task context, return to the 1170 * top level profile. 1171 * 1172 * change_hat only applies to profiles in the current ns, and each profile 1173 * in the ns must make the same transition otherwise change_hat will fail. 1174 */ 1175 int aa_change_hat(const char *hats[], int count, u64 token, int flags) 1176 { 1177 const struct cred *subj_cred; 1178 struct aa_task_ctx *ctx = task_ctx(current); 1179 struct aa_label *label, *previous, *new = NULL, *target = NULL; 1180 struct aa_profile *profile; 1181 struct aa_perms perms = {}; 1182 const char *info = NULL; 1183 int error = 0; 1184 1185 /* released below */ 1186 subj_cred = get_current_cred(); 1187 label = aa_get_newest_cred_label(subj_cred); 1188 previous = aa_get_newest_label(ctx->previous); 1189 1190 /* 1191 * Detect no new privs being set, and store the label it 1192 * occurred under. Ideally this would happen when nnp 1193 * is set but there isn't a good way to do that yet. 1194 * 1195 * Testing for unconfined must be done before the subset test 1196 */ 1197 if (task_no_new_privs(current) && !unconfined(label) && !ctx->nnp) 1198 ctx->nnp = aa_get_label(label); 1199 1200 if (unconfined(label)) { 1201 info = "unconfined can not change_hat"; 1202 error = -EPERM; 1203 goto fail; 1204 } 1205 1206 if (count) { 1207 new = change_hat(subj_cred, label, hats, count, flags); 1208 AA_BUG(!new); 1209 if (IS_ERR(new)) { 1210 error = PTR_ERR(new); 1211 new = NULL; 1212 /* already audited */ 1213 goto out; 1214 } 1215 1216 /* target cred is the same as current except new label */ 1217 error = may_change_ptraced_domain(subj_cred, new, &info); 1218 if (error) 1219 goto fail; 1220 1221 /* 1222 * no new privs prevents domain transitions that would 1223 * reduce restrictions. 1224 */ 1225 if (task_no_new_privs(current) && !unconfined(label) && 1226 !aa_label_is_unconfined_subset(new, ctx->nnp)) { 1227 /* not an apparmor denial per se, so don't log it */ 1228 AA_DEBUG("no_new_privs - change_hat denied"); 1229 error = -EPERM; 1230 goto out; 1231 } 1232 1233 if (flags & AA_CHANGE_TEST) 1234 goto out; 1235 1236 target = new; 1237 error = aa_set_current_hat(new, token); 1238 if (error == -EACCES) 1239 /* kill task in case of brute force attacks */ 1240 goto kill; 1241 } else if (previous && !(flags & AA_CHANGE_TEST)) { 1242 /* 1243 * no new privs prevents domain transitions that would 1244 * reduce restrictions. 1245 */ 1246 if (task_no_new_privs(current) && !unconfined(label) && 1247 !aa_label_is_unconfined_subset(previous, ctx->nnp)) { 1248 /* not an apparmor denial per se, so don't log it */ 1249 AA_DEBUG("no_new_privs - change_hat denied"); 1250 error = -EPERM; 1251 goto out; 1252 } 1253 1254 /* Return to saved label. Kill task if restore fails 1255 * to avoid brute force attacks 1256 */ 1257 target = previous; 1258 error = aa_restore_previous_label(token); 1259 if (error) { 1260 if (error == -EACCES) 1261 goto kill; 1262 goto fail; 1263 } 1264 } /* else ignore @flags && restores when there is no saved profile */ 1265 1266 out: 1267 aa_put_label(new); 1268 aa_put_label(previous); 1269 aa_put_label(label); 1270 put_cred(subj_cred); 1271 1272 return error; 1273 1274 kill: 1275 info = "failed token match"; 1276 perms.kill = AA_MAY_CHANGEHAT; 1277 1278 fail: 1279 fn_for_each_in_ns(label, profile, 1280 aa_audit_file(subj_cred, profile, &perms, OP_CHANGE_HAT, 1281 AA_MAY_CHANGEHAT, NULL, NULL, target, 1282 GLOBAL_ROOT_UID, info, error)); 1283 1284 goto out; 1285 } 1286 1287 1288 static int change_profile_perms_wrapper(const char *op, const char *name, 1289 const struct cred *subj_cred, 1290 struct aa_profile *profile, 1291 struct aa_label *target, bool stack, 1292 u32 request, struct aa_perms *perms) 1293 { 1294 struct aa_ruleset *rules = list_first_entry(&profile->rules, 1295 typeof(*rules), list); 1296 const char *info = NULL; 1297 int error = 0; 1298 1299 if (!error) 1300 error = change_profile_perms(profile, target, stack, request, 1301 rules->file.start[AA_CLASS_FILE], 1302 perms); 1303 if (error) 1304 error = aa_audit_file(subj_cred, profile, perms, op, request, 1305 name, 1306 NULL, target, GLOBAL_ROOT_UID, info, 1307 error); 1308 1309 return error; 1310 } 1311 1312 /** 1313 * aa_change_profile - perform a one-way profile transition 1314 * @fqname: name of profile may include namespace (NOT NULL) 1315 * @flags: flags affecting change behavior 1316 * 1317 * Change to new profile @name. Unlike with hats, there is no way 1318 * to change back. If @name isn't specified the current profile name is 1319 * used. 1320 * If @onexec then the transition is delayed until 1321 * the next exec. 1322 * 1323 * Returns %0 on success, error otherwise. 1324 */ 1325 int aa_change_profile(const char *fqname, int flags) 1326 { 1327 struct aa_label *label, *new = NULL, *target = NULL; 1328 struct aa_profile *profile; 1329 struct aa_perms perms = {}; 1330 const char *info = NULL; 1331 const char *auditname = fqname; /* retain leading & if stack */ 1332 bool stack = flags & AA_CHANGE_STACK; 1333 struct aa_task_ctx *ctx = task_ctx(current); 1334 const struct cred *subj_cred = get_current_cred(); 1335 int error = 0; 1336 char *op; 1337 u32 request; 1338 1339 label = aa_get_current_label(); 1340 1341 /* 1342 * Detect no new privs being set, and store the label it 1343 * occurred under. Ideally this would happen when nnp 1344 * is set but there isn't a good way to do that yet. 1345 * 1346 * Testing for unconfined must be done before the subset test 1347 */ 1348 if (task_no_new_privs(current) && !unconfined(label) && !ctx->nnp) 1349 ctx->nnp = aa_get_label(label); 1350 1351 if (!fqname || !*fqname) { 1352 aa_put_label(label); 1353 AA_DEBUG("no profile name"); 1354 return -EINVAL; 1355 } 1356 1357 if (flags & AA_CHANGE_ONEXEC) { 1358 request = AA_MAY_ONEXEC; 1359 if (stack) 1360 op = OP_STACK_ONEXEC; 1361 else 1362 op = OP_CHANGE_ONEXEC; 1363 } else { 1364 request = AA_MAY_CHANGE_PROFILE; 1365 if (stack) 1366 op = OP_STACK; 1367 else 1368 op = OP_CHANGE_PROFILE; 1369 } 1370 1371 if (*fqname == '&') { 1372 stack = true; 1373 /* don't have label_parse() do stacking */ 1374 fqname++; 1375 } 1376 target = aa_label_parse(label, fqname, GFP_KERNEL, true, false); 1377 if (IS_ERR(target)) { 1378 struct aa_profile *tprofile; 1379 1380 info = "label not found"; 1381 error = PTR_ERR(target); 1382 target = NULL; 1383 /* 1384 * TODO: fixme using labels_profile is not right - do profile 1385 * per complain profile 1386 */ 1387 if ((flags & AA_CHANGE_TEST) || 1388 !COMPLAIN_MODE(labels_profile(label))) 1389 goto audit; 1390 /* released below */ 1391 tprofile = aa_new_learning_profile(labels_profile(label), false, 1392 fqname, GFP_KERNEL); 1393 if (!tprofile) { 1394 info = "failed null profile create"; 1395 error = -ENOMEM; 1396 goto audit; 1397 } 1398 target = &tprofile->label; 1399 goto check; 1400 } 1401 1402 /* 1403 * self directed transitions only apply to current policy ns 1404 * TODO: currently requiring perms for stacking and straight change 1405 * stacking doesn't strictly need this. Determine how much 1406 * we want to loosen this restriction for stacking 1407 * 1408 * if (!stack) { 1409 */ 1410 error = fn_for_each_in_ns(label, profile, 1411 change_profile_perms_wrapper(op, auditname, 1412 subj_cred, 1413 profile, target, stack, 1414 request, &perms)); 1415 if (error) 1416 /* auditing done in change_profile_perms_wrapper */ 1417 goto out; 1418 1419 /* } */ 1420 1421 check: 1422 /* check if tracing task is allowed to trace target domain */ 1423 error = may_change_ptraced_domain(subj_cred, target, &info); 1424 if (error && !fn_for_each_in_ns(label, profile, 1425 COMPLAIN_MODE(profile))) 1426 goto audit; 1427 1428 /* TODO: add permission check to allow this 1429 * if ((flags & AA_CHANGE_ONEXEC) && !current_is_single_threaded()) { 1430 * info = "not a single threaded task"; 1431 * error = -EACCES; 1432 * goto audit; 1433 * } 1434 */ 1435 if (flags & AA_CHANGE_TEST) 1436 goto out; 1437 1438 /* stacking is always a subset, so only check the nonstack case */ 1439 if (!stack) { 1440 new = fn_label_build_in_ns(label, profile, GFP_KERNEL, 1441 aa_get_label(target), 1442 aa_get_label(&profile->label)); 1443 /* 1444 * no new privs prevents domain transitions that would 1445 * reduce restrictions. 1446 */ 1447 if (task_no_new_privs(current) && !unconfined(label) && 1448 !aa_label_is_unconfined_subset(new, ctx->nnp)) { 1449 /* not an apparmor denial per se, so don't log it */ 1450 AA_DEBUG("no_new_privs - change_hat denied"); 1451 error = -EPERM; 1452 goto out; 1453 } 1454 } 1455 1456 if (!(flags & AA_CHANGE_ONEXEC)) { 1457 /* only transition profiles in the current ns */ 1458 if (stack) 1459 new = aa_label_merge(label, target, GFP_KERNEL); 1460 if (IS_ERR_OR_NULL(new)) { 1461 info = "failed to build target label"; 1462 if (!new) 1463 error = -ENOMEM; 1464 else 1465 error = PTR_ERR(new); 1466 new = NULL; 1467 perms.allow = 0; 1468 goto audit; 1469 } 1470 error = aa_replace_current_label(new); 1471 } else { 1472 if (new) { 1473 aa_put_label(new); 1474 new = NULL; 1475 } 1476 1477 /* full transition will be built in exec path */ 1478 error = aa_set_current_onexec(target, stack); 1479 } 1480 1481 audit: 1482 error = fn_for_each_in_ns(label, profile, 1483 aa_audit_file(subj_cred, 1484 profile, &perms, op, request, auditname, 1485 NULL, new ? new : target, 1486 GLOBAL_ROOT_UID, info, error)); 1487 1488 out: 1489 aa_put_label(new); 1490 aa_put_label(target); 1491 aa_put_label(label); 1492 put_cred(subj_cred); 1493 1494 return error; 1495 } 1496