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