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