1 /* 2 * AppArmor security module 3 * 4 * This file contains AppArmor policy attachment and domain transitions 5 * 6 * Copyright (C) 2002-2008 Novell/SUSE 7 * Copyright 2009-2010 Canonical Ltd. 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation, version 2 of the 12 * License. 13 */ 14 15 #include <linux/errno.h> 16 #include <linux/fdtable.h> 17 #include <linux/file.h> 18 #include <linux/mount.h> 19 #include <linux/syscalls.h> 20 #include <linux/tracehook.h> 21 #include <linux/personality.h> 22 23 #include "include/audit.h" 24 #include "include/apparmorfs.h" 25 #include "include/context.h" 26 #include "include/domain.h" 27 #include "include/file.h" 28 #include "include/ipc.h" 29 #include "include/match.h" 30 #include "include/path.h" 31 #include "include/policy.h" 32 #include "include/policy_ns.h" 33 34 /** 35 * aa_free_domain_entries - free entries in a domain table 36 * @domain: the domain table to free (MAYBE NULL) 37 */ 38 void aa_free_domain_entries(struct aa_domain *domain) 39 { 40 int i; 41 if (domain) { 42 if (!domain->table) 43 return; 44 45 for (i = 0; i < domain->size; i++) 46 kzfree(domain->table[i]); 47 kzfree(domain->table); 48 domain->table = NULL; 49 } 50 } 51 52 /** 53 * may_change_ptraced_domain - check if can change profile on ptraced task 54 * @to_profile: profile to change to (NOT NULL) 55 * 56 * Check if current is ptraced and if so if the tracing task is allowed 57 * to trace the new domain 58 * 59 * Returns: %0 or error if change not allowed 60 */ 61 static int may_change_ptraced_domain(struct aa_profile *to_profile) 62 { 63 struct task_struct *tracer; 64 struct aa_profile *tracerp = NULL; 65 int error = 0; 66 67 rcu_read_lock(); 68 tracer = ptrace_parent(current); 69 if (tracer) 70 /* released below */ 71 tracerp = aa_get_task_profile(tracer); 72 73 /* not ptraced */ 74 if (!tracer || unconfined(tracerp)) 75 goto out; 76 77 error = aa_may_ptrace(tracerp, to_profile, PTRACE_MODE_ATTACH); 78 79 out: 80 rcu_read_unlock(); 81 aa_put_profile(tracerp); 82 83 return error; 84 } 85 86 /** 87 * change_profile_perms - find permissions for change_profile 88 * @profile: the current profile (NOT NULL) 89 * @ns: the namespace being switched to (NOT NULL) 90 * @name: the name of the profile to change to (NOT NULL) 91 * @request: requested perms 92 * @start: state to start matching in 93 * 94 * Returns: permission set 95 */ 96 static struct file_perms change_profile_perms(struct aa_profile *profile, 97 struct aa_ns *ns, 98 const char *name, u32 request, 99 unsigned int start) 100 { 101 struct file_perms perms; 102 struct path_cond cond = { }; 103 unsigned int state; 104 105 if (unconfined(profile)) { 106 perms.allow = AA_MAY_CHANGE_PROFILE | AA_MAY_ONEXEC; 107 perms.audit = perms.quiet = perms.kill = 0; 108 return perms; 109 } else if (!profile->file.dfa) { 110 return nullperms; 111 } else if ((ns == profile->ns)) { 112 /* try matching against rules with out namespace prepended */ 113 aa_str_perms(profile->file.dfa, start, name, &cond, &perms); 114 if (COMBINED_PERM_MASK(perms) & request) 115 return perms; 116 } 117 118 /* try matching with namespace name and then profile */ 119 state = aa_dfa_match(profile->file.dfa, start, ns->base.name); 120 state = aa_dfa_match_len(profile->file.dfa, state, ":", 1); 121 aa_str_perms(profile->file.dfa, state, name, &cond, &perms); 122 123 return perms; 124 } 125 126 /** 127 * __attach_match_ - find an attachment match 128 * @name - to match against (NOT NULL) 129 * @head - profile list to walk (NOT NULL) 130 * 131 * Do a linear search on the profiles in the list. There is a matching 132 * preference where an exact match is preferred over a name which uses 133 * expressions to match, and matching expressions with the greatest 134 * xmatch_len are preferred. 135 * 136 * Requires: @head not be shared or have appropriate locks held 137 * 138 * Returns: profile or NULL if no match found 139 */ 140 static struct aa_profile *__attach_match(const char *name, 141 struct list_head *head) 142 { 143 int len = 0; 144 struct aa_profile *profile, *candidate = NULL; 145 146 list_for_each_entry_rcu(profile, head, base.list) { 147 if (profile->flags & PFLAG_NULL) 148 continue; 149 if (profile->xmatch && profile->xmatch_len > len) { 150 unsigned int state = aa_dfa_match(profile->xmatch, 151 DFA_START, name); 152 u32 perm = dfa_user_allow(profile->xmatch, state); 153 /* any accepting state means a valid match. */ 154 if (perm & MAY_EXEC) { 155 candidate = profile; 156 len = profile->xmatch_len; 157 } 158 } else if (!strcmp(profile->base.name, name)) 159 /* exact non-re match, no more searching required */ 160 return profile; 161 } 162 163 return candidate; 164 } 165 166 /** 167 * find_attach - do attachment search for unconfined processes 168 * @ns: the current namespace (NOT NULL) 169 * @list: list to search (NOT NULL) 170 * @name: the executable name to match against (NOT NULL) 171 * 172 * Returns: profile or NULL if no match found 173 */ 174 static struct aa_profile *find_attach(struct aa_ns *ns, 175 struct list_head *list, const char *name) 176 { 177 struct aa_profile *profile; 178 179 rcu_read_lock(); 180 profile = aa_get_profile(__attach_match(name, list)); 181 rcu_read_unlock(); 182 183 return profile; 184 } 185 186 /** 187 * separate_fqname - separate the namespace and profile names 188 * @fqname: the fqname name to split (NOT NULL) 189 * @ns_name: the namespace name if it exists (NOT NULL) 190 * 191 * This is the xtable equivalent routine of aa_split_fqname. It finds the 192 * split in an xtable fqname which contains an embedded \0 instead of a : 193 * if a namespace is specified. This is done so the xtable is constant and 194 * isn't re-split on every lookup. 195 * 196 * Either the profile or namespace name may be optional but if the namespace 197 * is specified the profile name termination must be present. This results 198 * in the following possible encodings: 199 * profile_name\0 200 * :ns_name\0profile_name\0 201 * :ns_name\0\0 202 * 203 * NOTE: the xtable fqname is pre-validated at load time in unpack_trans_table 204 * 205 * Returns: profile name if it is specified else NULL 206 */ 207 static const char *separate_fqname(const char *fqname, const char **ns_name) 208 { 209 const char *name; 210 211 if (fqname[0] == ':') { 212 /* In this case there is guaranteed to be two \0 terminators 213 * in the string. They are verified at load time by 214 * by unpack_trans_table 215 */ 216 *ns_name = fqname + 1; /* skip : */ 217 name = *ns_name + strlen(*ns_name) + 1; 218 if (!*name) 219 name = NULL; 220 } else { 221 *ns_name = NULL; 222 name = fqname; 223 } 224 225 return name; 226 } 227 228 static const char *next_name(int xtype, const char *name) 229 { 230 return NULL; 231 } 232 233 /** 234 * x_table_lookup - lookup an x transition name via transition table 235 * @profile: current profile (NOT NULL) 236 * @xindex: index into x transition table 237 * 238 * Returns: refcounted profile, or NULL on failure (MAYBE NULL) 239 */ 240 static struct aa_profile *x_table_lookup(struct aa_profile *profile, u32 xindex) 241 { 242 struct aa_profile *new_profile = NULL; 243 struct aa_ns *ns = profile->ns; 244 u32 xtype = xindex & AA_X_TYPE_MASK; 245 int index = xindex & AA_X_INDEX_MASK; 246 const char *name; 247 248 /* index is guaranteed to be in range, validated at load time */ 249 for (name = profile->file.trans.table[index]; !new_profile && name; 250 name = next_name(xtype, name)) { 251 struct aa_ns *new_ns; 252 const char *xname = NULL; 253 254 new_ns = NULL; 255 if (xindex & AA_X_CHILD) { 256 /* release by caller */ 257 new_profile = aa_find_child(profile, name); 258 continue; 259 } else if (*name == ':') { 260 /* switching namespace */ 261 const char *ns_name; 262 xname = name = separate_fqname(name, &ns_name); 263 if (!xname) 264 /* no name so use profile name */ 265 xname = profile->base.hname; 266 if (*ns_name == '@') { 267 /* TODO: variable support */ 268 ; 269 } 270 /* released below */ 271 new_ns = aa_find_ns(ns, ns_name); 272 if (!new_ns) 273 continue; 274 } else if (*name == '@') { 275 /* TODO: variable support */ 276 continue; 277 } else { 278 /* basic namespace lookup */ 279 xname = name; 280 } 281 282 /* released by caller */ 283 new_profile = aa_lookup_profile(new_ns ? new_ns : ns, xname); 284 aa_put_ns(new_ns); 285 } 286 287 /* released by caller */ 288 return new_profile; 289 } 290 291 /** 292 * x_to_profile - get target profile for a given xindex 293 * @profile: current profile (NOT NULL) 294 * @name: name to lookup (NOT NULL) 295 * @xindex: index into x transition table 296 * 297 * find profile for a transition index 298 * 299 * Returns: refcounted profile or NULL if not found available 300 */ 301 static struct aa_profile *x_to_profile(struct aa_profile *profile, 302 const char *name, u32 xindex) 303 { 304 struct aa_profile *new_profile = NULL; 305 struct aa_ns *ns = profile->ns; 306 u32 xtype = xindex & AA_X_TYPE_MASK; 307 308 switch (xtype) { 309 case AA_X_NONE: 310 /* fail exec unless ix || ux fallback - handled by caller */ 311 return NULL; 312 case AA_X_NAME: 313 if (xindex & AA_X_CHILD) 314 /* released by caller */ 315 new_profile = find_attach(ns, &profile->base.profiles, 316 name); 317 else 318 /* released by caller */ 319 new_profile = find_attach(ns, &ns->base.profiles, 320 name); 321 break; 322 case AA_X_TABLE: 323 /* released by caller */ 324 new_profile = x_table_lookup(profile, xindex); 325 break; 326 } 327 328 /* released by caller */ 329 return new_profile; 330 } 331 332 /** 333 * apparmor_bprm_set_creds - set the new creds on the bprm struct 334 * @bprm: binprm for the exec (NOT NULL) 335 * 336 * Returns: %0 or error on failure 337 */ 338 int apparmor_bprm_set_creds(struct linux_binprm *bprm) 339 { 340 struct aa_task_ctx *ctx; 341 struct aa_profile *profile, *new_profile = NULL; 342 struct aa_ns *ns; 343 char *buffer = NULL; 344 unsigned int state; 345 struct file_perms perms = {}; 346 struct path_cond cond = { 347 file_inode(bprm->file)->i_uid, 348 file_inode(bprm->file)->i_mode 349 }; 350 const char *name = NULL, *info = NULL; 351 int error = 0; 352 353 if (bprm->cred_prepared) 354 return 0; 355 356 ctx = cred_ctx(bprm->cred); 357 AA_BUG(!ctx); 358 359 profile = aa_get_newest_profile(ctx->profile); 360 /* 361 * get the namespace from the replacement profile as replacement 362 * can change the namespace 363 */ 364 ns = profile->ns; 365 state = profile->file.start; 366 367 /* buffer freed below, name is pointer into buffer */ 368 error = aa_path_name(&bprm->file->f_path, profile->path_flags, &buffer, 369 &name, &info); 370 if (error) { 371 if (unconfined(profile) || 372 (profile->flags & PFLAG_IX_ON_NAME_ERROR)) 373 error = 0; 374 name = bprm->filename; 375 goto audit; 376 } 377 378 /* Test for onexec first as onexec directives override other 379 * x transitions. 380 */ 381 if (unconfined(profile)) { 382 /* unconfined task */ 383 if (ctx->onexec) 384 /* change_profile on exec already been granted */ 385 new_profile = aa_get_profile(ctx->onexec); 386 else 387 new_profile = find_attach(ns, &ns->base.profiles, name); 388 if (!new_profile) 389 goto cleanup; 390 /* 391 * NOTE: Domain transitions from unconfined are allowed 392 * even when no_new_privs is set because this aways results 393 * in a further reduction of permissions. 394 */ 395 goto apply; 396 } 397 398 /* find exec permissions for name */ 399 state = aa_str_perms(profile->file.dfa, state, name, &cond, &perms); 400 if (ctx->onexec) { 401 struct file_perms cp; 402 info = "change_profile onexec"; 403 new_profile = aa_get_newest_profile(ctx->onexec); 404 if (!(perms.allow & AA_MAY_ONEXEC)) 405 goto audit; 406 407 /* test if this exec can be paired with change_profile onexec. 408 * onexec permission is linked to exec with a standard pairing 409 * exec\0change_profile 410 */ 411 state = aa_dfa_null_transition(profile->file.dfa, state); 412 cp = change_profile_perms(profile, ctx->onexec->ns, 413 ctx->onexec->base.name, 414 AA_MAY_ONEXEC, state); 415 416 if (!(cp.allow & AA_MAY_ONEXEC)) 417 goto audit; 418 goto apply; 419 } 420 421 if (perms.allow & MAY_EXEC) { 422 /* exec permission determine how to transition */ 423 new_profile = x_to_profile(profile, name, perms.xindex); 424 if (!new_profile) { 425 if (perms.xindex & AA_X_INHERIT) { 426 /* (p|c|n)ix - don't change profile but do 427 * use the newest version, which was picked 428 * up above when getting profile 429 */ 430 info = "ix fallback"; 431 new_profile = aa_get_profile(profile); 432 goto x_clear; 433 } else if (perms.xindex & AA_X_UNCONFINED) { 434 new_profile = aa_get_newest_profile(ns->unconfined); 435 info = "ux fallback"; 436 } else { 437 error = -EACCES; 438 info = "profile not found"; 439 /* remove MAY_EXEC to audit as failure */ 440 perms.allow &= ~MAY_EXEC; 441 } 442 } 443 } else if (COMPLAIN_MODE(profile)) { 444 /* no exec permission - are we in learning mode */ 445 new_profile = aa_new_null_profile(profile, false, name, 446 GFP_ATOMIC); 447 if (!new_profile) { 448 error = -ENOMEM; 449 info = "could not create null profile"; 450 } else 451 error = -EACCES; 452 perms.xindex |= AA_X_UNSAFE; 453 } else 454 /* fail exec */ 455 error = -EACCES; 456 457 /* 458 * Policy has specified a domain transition, if no_new_privs then 459 * fail the exec. 460 */ 461 if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) { 462 error = -EPERM; 463 goto cleanup; 464 } 465 466 if (!new_profile) 467 goto audit; 468 469 if (bprm->unsafe & LSM_UNSAFE_SHARE) { 470 /* FIXME: currently don't mediate shared state */ 471 ; 472 } 473 474 if (bprm->unsafe & LSM_UNSAFE_PTRACE) { 475 error = may_change_ptraced_domain(new_profile); 476 if (error) 477 goto audit; 478 } 479 480 /* Determine if secure exec is needed. 481 * Can be at this point for the following reasons: 482 * 1. unconfined switching to confined 483 * 2. confined switching to different confinement 484 * 3. confined switching to unconfined 485 * 486 * Cases 2 and 3 are marked as requiring secure exec 487 * (unless policy specified "unsafe exec") 488 * 489 * bprm->unsafe is used to cache the AA_X_UNSAFE permission 490 * to avoid having to recompute in secureexec 491 */ 492 if (!(perms.xindex & AA_X_UNSAFE)) { 493 AA_DEBUG("scrubbing environment variables for %s profile=%s\n", 494 name, new_profile->base.hname); 495 bprm->unsafe |= AA_SECURE_X_NEEDED; 496 } 497 apply: 498 /* when transitioning profiles clear unsafe personality bits */ 499 bprm->per_clear |= PER_CLEAR_ON_SETID; 500 501 x_clear: 502 aa_put_profile(ctx->profile); 503 /* transfer new profile reference will be released when ctx is freed */ 504 ctx->profile = new_profile; 505 new_profile = NULL; 506 507 /* clear out all temporary/transitional state from the context */ 508 aa_clear_task_ctx_trans(ctx); 509 510 audit: 511 error = aa_audit_file(profile, &perms, OP_EXEC, MAY_EXEC, name, 512 new_profile ? new_profile->base.hname : NULL, 513 cond.uid, info, error); 514 515 cleanup: 516 aa_put_profile(new_profile); 517 aa_put_profile(profile); 518 kfree(buffer); 519 520 return error; 521 } 522 523 /** 524 * apparmor_bprm_secureexec - determine if secureexec is needed 525 * @bprm: binprm for exec (NOT NULL) 526 * 527 * Returns: %1 if secureexec is needed else %0 528 */ 529 int apparmor_bprm_secureexec(struct linux_binprm *bprm) 530 { 531 /* the decision to use secure exec is computed in set_creds 532 * and stored in bprm->unsafe. 533 */ 534 if (bprm->unsafe & AA_SECURE_X_NEEDED) 535 return 1; 536 537 return 0; 538 } 539 540 /** 541 * apparmor_bprm_committing_creds - do task cleanup on committing new creds 542 * @bprm: binprm for the exec (NOT NULL) 543 */ 544 void apparmor_bprm_committing_creds(struct linux_binprm *bprm) 545 { 546 struct aa_profile *profile = __aa_current_profile(); 547 struct aa_task_ctx *new_ctx = cred_ctx(bprm->cred); 548 549 /* bail out if unconfined or not changing profile */ 550 if ((new_ctx->profile == profile) || 551 (unconfined(new_ctx->profile))) 552 return; 553 554 current->pdeath_signal = 0; 555 556 /* reset soft limits and set hard limits for the new profile */ 557 __aa_transition_rlimits(profile, new_ctx->profile); 558 } 559 560 /** 561 * apparmor_bprm_commited_cred - do cleanup after new creds committed 562 * @bprm: binprm for the exec (NOT NULL) 563 */ 564 void apparmor_bprm_committed_creds(struct linux_binprm *bprm) 565 { 566 /* TODO: cleanup signals - ipc mediation */ 567 return; 568 } 569 570 /* 571 * Functions for self directed profile change 572 */ 573 574 /** 575 * new_compound_name - create an hname with @n2 appended to @n1 576 * @n1: base of hname (NOT NULL) 577 * @n2: name to append (NOT NULL) 578 * 579 * Returns: new name or NULL on error 580 */ 581 static char *new_compound_name(const char *n1, const char *n2) 582 { 583 char *name = kmalloc(strlen(n1) + strlen(n2) + 3, GFP_KERNEL); 584 if (name) 585 sprintf(name, "%s//%s", n1, n2); 586 return name; 587 } 588 589 /** 590 * aa_change_hat - change hat to/from subprofile 591 * @hats: vector of hat names to try changing into (MAYBE NULL if @count == 0) 592 * @count: number of hat names in @hats 593 * @token: magic value to validate the hat change 594 * @permtest: true if this is just a permission test 595 * 596 * Change to the first profile specified in @hats that exists, and store 597 * the @hat_magic in the current task context. If the count == 0 and the 598 * @token matches that stored in the current task context, return to the 599 * top level profile. 600 * 601 * Returns %0 on success, error otherwise. 602 */ 603 int aa_change_hat(const char *hats[], int count, u64 token, bool permtest) 604 { 605 const struct cred *cred; 606 struct aa_task_ctx *ctx; 607 struct aa_profile *profile, *previous_profile, *hat = NULL; 608 char *name = NULL; 609 int i; 610 struct file_perms perms = {}; 611 const char *target = NULL, *info = NULL; 612 int error = 0; 613 614 /* 615 * Fail explicitly requested domain transitions if no_new_privs. 616 * There is no exception for unconfined as change_hat is not 617 * available. 618 */ 619 if (task_no_new_privs(current)) 620 return -EPERM; 621 622 /* released below */ 623 cred = get_current_cred(); 624 ctx = cred_ctx(cred); 625 profile = aa_get_newest_profile(aa_cred_profile(cred)); 626 previous_profile = aa_get_newest_profile(ctx->previous); 627 628 if (unconfined(profile)) { 629 info = "unconfined"; 630 error = -EPERM; 631 goto audit; 632 } 633 634 if (count) { 635 /* attempting to change into a new hat or switch to a sibling */ 636 struct aa_profile *root; 637 if (PROFILE_IS_HAT(profile)) 638 root = aa_get_profile_rcu(&profile->parent); 639 else 640 root = aa_get_profile(profile); 641 642 /* find first matching hat */ 643 for (i = 0; i < count && !hat; i++) 644 /* released below */ 645 hat = aa_find_child(root, hats[i]); 646 if (!hat) { 647 if (!COMPLAIN_MODE(root) || permtest) { 648 if (list_empty(&root->base.profiles)) 649 error = -ECHILD; 650 else 651 error = -ENOENT; 652 aa_put_profile(root); 653 goto out; 654 } 655 656 /* 657 * In complain mode and failed to match any hats. 658 * Audit the failure is based off of the first hat 659 * supplied. This is done due how userspace 660 * interacts with change_hat. 661 * 662 * TODO: Add logging of all failed hats 663 */ 664 665 /* freed below */ 666 name = new_compound_name(root->base.hname, hats[0]); 667 aa_put_profile(root); 668 target = name; 669 /* released below */ 670 hat = aa_new_null_profile(profile, true, hats[0], 671 GFP_KERNEL); 672 if (!hat) { 673 info = "failed null profile create"; 674 error = -ENOMEM; 675 goto audit; 676 } 677 } else { 678 aa_put_profile(root); 679 target = hat->base.hname; 680 if (!PROFILE_IS_HAT(hat)) { 681 info = "target not hat"; 682 error = -EPERM; 683 goto audit; 684 } 685 } 686 687 error = may_change_ptraced_domain(hat); 688 if (error) { 689 info = "ptraced"; 690 error = -EPERM; 691 goto audit; 692 } 693 694 if (!permtest) { 695 error = aa_set_current_hat(hat, token); 696 if (error == -EACCES) 697 /* kill task in case of brute force attacks */ 698 perms.kill = AA_MAY_CHANGEHAT; 699 else if (name && !error) 700 /* reset error for learning of new hats */ 701 error = -ENOENT; 702 } 703 } else if (previous_profile) { 704 /* Return to saved profile. Kill task if restore fails 705 * to avoid brute force attacks 706 */ 707 target = previous_profile->base.hname; 708 error = aa_restore_previous_profile(token); 709 perms.kill = AA_MAY_CHANGEHAT; 710 } else 711 /* ignore restores when there is no saved profile */ 712 goto out; 713 714 audit: 715 if (!permtest) 716 error = aa_audit_file(profile, &perms, OP_CHANGE_HAT, 717 AA_MAY_CHANGEHAT, NULL, target, 718 GLOBAL_ROOT_UID, info, error); 719 720 out: 721 aa_put_profile(hat); 722 kfree(name); 723 aa_put_profile(profile); 724 aa_put_profile(previous_profile); 725 put_cred(cred); 726 727 return error; 728 } 729 730 /** 731 * aa_change_profile - perform a one-way profile transition 732 * @fqname: name of profile may include namespace (NOT NULL) 733 * @onexec: whether this transition is to take place immediately or at exec 734 * @permtest: true if this is just a permission test 735 * 736 * Change to new profile @name. Unlike with hats, there is no way 737 * to change back. If @name isn't specified the current profile name is 738 * used. 739 * If @onexec then the transition is delayed until 740 * the next exec. 741 * 742 * Returns %0 on success, error otherwise. 743 */ 744 int aa_change_profile(const char *fqname, bool onexec, 745 bool permtest, bool stack) 746 { 747 const struct cred *cred; 748 struct aa_profile *profile, *target = NULL; 749 struct file_perms perms = {}; 750 const char *info = NULL, *op; 751 int error = 0; 752 u32 request; 753 754 if (!fqname || !*fqname) { 755 AA_DEBUG("no profile name"); 756 return -EINVAL; 757 } 758 759 if (onexec) { 760 request = AA_MAY_ONEXEC; 761 op = OP_CHANGE_ONEXEC; 762 } else { 763 request = AA_MAY_CHANGE_PROFILE; 764 op = OP_CHANGE_PROFILE; 765 } 766 767 cred = get_current_cred(); 768 profile = aa_cred_profile(cred); 769 770 /* 771 * Fail explicitly requested domain transitions if no_new_privs 772 * and not unconfined. 773 * Domain transitions from unconfined are allowed even when 774 * no_new_privs is set because this aways results in a reduction 775 * of permissions. 776 */ 777 if (task_no_new_privs(current) && !unconfined(profile)) { 778 put_cred(cred); 779 return -EPERM; 780 } 781 782 target = aa_fqlookupn_profile(profile, fqname, strlen(fqname)); 783 if (!target) { 784 info = "profile not found"; 785 error = -ENOENT; 786 if (permtest || !COMPLAIN_MODE(profile)) 787 goto audit; 788 /* released below */ 789 target = aa_new_null_profile(profile, false, fqname, 790 GFP_KERNEL); 791 if (!target) { 792 info = "failed null profile create"; 793 error = -ENOMEM; 794 goto audit; 795 } 796 } 797 798 perms = change_profile_perms(profile, target->ns, target->base.hname, 799 request, profile->file.start); 800 if (!(perms.allow & request)) { 801 error = -EACCES; 802 goto audit; 803 } 804 805 /* check if tracing task is allowed to trace target domain */ 806 error = may_change_ptraced_domain(target); 807 if (error) { 808 info = "ptrace prevents transition"; 809 goto audit; 810 } 811 812 if (permtest) 813 goto audit; 814 815 if (onexec) 816 error = aa_set_current_onexec(target); 817 else 818 error = aa_replace_current_profile(target); 819 820 audit: 821 if (!permtest) 822 error = aa_audit_file(profile, &perms, op, request, NULL, 823 fqname, GLOBAL_ROOT_UID, info, error); 824 825 aa_put_profile(target); 826 put_cred(cred); 827 828 return error; 829 } 830