linux/security/apparmor/file.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * AppArmor security module
   4 *
   5 * This file contains AppArmor mediation of files
   6 *
   7 * Copyright (C) 1998-2008 Novell/SUSE
   8 * Copyright 2009-2010 Canonical Ltd.
   9 */
  10
  11#include <linux/tty.h>
  12#include <linux/fdtable.h>
  13#include <linux/file.h>
  14#include <linux/fs.h>
  15#include <linux/mount.h>
  16
  17#include "include/apparmor.h"
  18#include "include/audit.h"
  19#include "include/cred.h"
  20#include "include/file.h"
  21#include "include/match.h"
  22#include "include/net.h"
  23#include "include/path.h"
  24#include "include/policy.h"
  25#include "include/label.h"
  26
  27static u32 map_mask_to_chr_mask(u32 mask)
  28{
  29        u32 m = mask & PERMS_CHRS_MASK;
  30
  31        if (mask & AA_MAY_GETATTR)
  32                m |= MAY_READ;
  33        if (mask & (AA_MAY_SETATTR | AA_MAY_CHMOD | AA_MAY_CHOWN))
  34                m |= MAY_WRITE;
  35
  36        return m;
  37}
  38
  39/**
  40 * file_audit_cb - call back for file specific audit fields
  41 * @ab: audit_buffer  (NOT NULL)
  42 * @va: audit struct to audit values of  (NOT NULL)
  43 */
  44static void file_audit_cb(struct audit_buffer *ab, void *va)
  45{
  46        struct common_audit_data *sa = va;
  47        kuid_t fsuid = current_fsuid();
  48        char str[10];
  49
  50        if (aad(sa)->request & AA_AUDIT_FILE_MASK) {
  51                aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs,
  52                                    map_mask_to_chr_mask(aad(sa)->request));
  53                audit_log_format(ab, " requested_mask=\"%s\"", str);
  54        }
  55        if (aad(sa)->denied & AA_AUDIT_FILE_MASK) {
  56                aa_perm_mask_to_str(str, sizeof(str), aa_file_perm_chrs,
  57                                    map_mask_to_chr_mask(aad(sa)->denied));
  58                audit_log_format(ab, " denied_mask=\"%s\"", str);
  59        }
  60        if (aad(sa)->request & AA_AUDIT_FILE_MASK) {
  61                audit_log_format(ab, " fsuid=%d",
  62                                 from_kuid(&init_user_ns, fsuid));
  63                audit_log_format(ab, " ouid=%d",
  64                                 from_kuid(&init_user_ns, aad(sa)->fs.ouid));
  65        }
  66
  67        if (aad(sa)->peer) {
  68                audit_log_format(ab, " target=");
  69                aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
  70                                FLAG_VIEW_SUBNS, GFP_KERNEL);
  71        } else if (aad(sa)->fs.target) {
  72                audit_log_format(ab, " target=");
  73                audit_log_untrustedstring(ab, aad(sa)->fs.target);
  74        }
  75}
  76
  77/**
  78 * aa_audit_file - handle the auditing of file operations
  79 * @profile: the profile being enforced  (NOT NULL)
  80 * @perms: the permissions computed for the request (NOT NULL)
  81 * @op: operation being mediated
  82 * @request: permissions requested
  83 * @name: name of object being mediated (MAYBE NULL)
  84 * @target: name of target (MAYBE NULL)
  85 * @tlabel: target label (MAY BE NULL)
  86 * @ouid: object uid
  87 * @info: extra information message (MAYBE NULL)
  88 * @error: 0 if operation allowed else failure error code
  89 *
  90 * Returns: %0 or error on failure
  91 */
  92int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms,
  93                  const char *op, u32 request, const char *name,
  94                  const char *target, struct aa_label *tlabel,
  95                  kuid_t ouid, const char *info, int error)
  96{
  97        int type = AUDIT_APPARMOR_AUTO;
  98        DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, op);
  99
 100        sa.u.tsk = NULL;
 101        aad(&sa)->request = request;
 102        aad(&sa)->name = name;
 103        aad(&sa)->fs.target = target;
 104        aad(&sa)->peer = tlabel;
 105        aad(&sa)->fs.ouid = ouid;
 106        aad(&sa)->info = info;
 107        aad(&sa)->error = error;
 108        sa.u.tsk = NULL;
 109
 110        if (likely(!aad(&sa)->error)) {
 111                u32 mask = perms->audit;
 112
 113                if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
 114                        mask = 0xffff;
 115
 116                /* mask off perms that are not being force audited */
 117                aad(&sa)->request &= mask;
 118
 119                if (likely(!aad(&sa)->request))
 120                        return 0;
 121                type = AUDIT_APPARMOR_AUDIT;
 122        } else {
 123                /* only report permissions that were denied */
 124                aad(&sa)->request = aad(&sa)->request & ~perms->allow;
 125                AA_BUG(!aad(&sa)->request);
 126
 127                if (aad(&sa)->request & perms->kill)
 128                        type = AUDIT_APPARMOR_KILL;
 129
 130                /* quiet known rejects, assumes quiet and kill do not overlap */
 131                if ((aad(&sa)->request & perms->quiet) &&
 132                    AUDIT_MODE(profile) != AUDIT_NOQUIET &&
 133                    AUDIT_MODE(profile) != AUDIT_ALL)
 134                        aad(&sa)->request &= ~perms->quiet;
 135
 136                if (!aad(&sa)->request)
 137                        return aad(&sa)->error;
 138        }
 139
 140        aad(&sa)->denied = aad(&sa)->request & ~perms->allow;
 141        return aa_audit(type, profile, &sa, file_audit_cb);
 142}
 143
 144/**
 145 * is_deleted - test if a file has been completely unlinked
 146 * @dentry: dentry of file to test for deletion  (NOT NULL)
 147 *
 148 * Returns: true if deleted else false
 149 */
 150static inline bool is_deleted(struct dentry *dentry)
 151{
 152        if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0)
 153                return true;
 154        return false;
 155}
 156
 157static int path_name(const char *op, struct aa_label *label,
 158                     const struct path *path, int flags, char *buffer,
 159                     const char **name, struct path_cond *cond, u32 request)
 160{
 161        struct aa_profile *profile;
 162        const char *info = NULL;
 163        int error;
 164
 165        error = aa_path_name(path, flags, buffer, name, &info,
 166                             labels_profile(label)->disconnected);
 167        if (error) {
 168                fn_for_each_confined(label, profile,
 169                        aa_audit_file(profile, &nullperms, op, request, *name,
 170                                      NULL, NULL, cond->uid, info, error));
 171                return error;
 172        }
 173
 174        return 0;
 175}
 176
 177/**
 178 * map_old_perms - map old file perms layout to the new layout
 179 * @old: permission set in old mapping
 180 *
 181 * Returns: new permission mapping
 182 */
 183static u32 map_old_perms(u32 old)
 184{
 185        u32 new = old & 0xf;
 186        if (old & MAY_READ)
 187                new |= AA_MAY_GETATTR | AA_MAY_OPEN;
 188        if (old & MAY_WRITE)
 189                new |= AA_MAY_SETATTR | AA_MAY_CREATE | AA_MAY_DELETE |
 190                       AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_OPEN;
 191        if (old & 0x10)
 192                new |= AA_MAY_LINK;
 193        /* the old mapping lock and link_subset flags where overlaid
 194         * and use was determined by part of a pair that they were in
 195         */
 196        if (old & 0x20)
 197                new |= AA_MAY_LOCK | AA_LINK_SUBSET;
 198        if (old & 0x40) /* AA_EXEC_MMAP */
 199                new |= AA_EXEC_MMAP;
 200
 201        return new;
 202}
 203
 204/**
 205 * aa_compute_fperms - convert dfa compressed perms to internal perms
 206 * @dfa: dfa to compute perms for   (NOT NULL)
 207 * @state: state in dfa
 208 * @cond:  conditions to consider  (NOT NULL)
 209 *
 210 * TODO: convert from dfa + state to permission entry, do computation conversion
 211 *       at load time.
 212 *
 213 * Returns: computed permission set
 214 */
 215struct aa_perms aa_compute_fperms(struct aa_dfa *dfa, unsigned int state,
 216                                  struct path_cond *cond)
 217{
 218        /* FIXME: change over to new dfa format
 219         * currently file perms are encoded in the dfa, new format
 220         * splits the permissions from the dfa.  This mapping can be
 221         * done at profile load
 222         */
 223        struct aa_perms perms = { };
 224
 225        if (uid_eq(current_fsuid(), cond->uid)) {
 226                perms.allow = map_old_perms(dfa_user_allow(dfa, state));
 227                perms.audit = map_old_perms(dfa_user_audit(dfa, state));
 228                perms.quiet = map_old_perms(dfa_user_quiet(dfa, state));
 229                perms.xindex = dfa_user_xindex(dfa, state);
 230        } else {
 231                perms.allow = map_old_perms(dfa_other_allow(dfa, state));
 232                perms.audit = map_old_perms(dfa_other_audit(dfa, state));
 233                perms.quiet = map_old_perms(dfa_other_quiet(dfa, state));
 234                perms.xindex = dfa_other_xindex(dfa, state);
 235        }
 236        perms.allow |= AA_MAY_GETATTR;
 237
 238        /* change_profile wasn't determined by ownership in old mapping */
 239        if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
 240                perms.allow |= AA_MAY_CHANGE_PROFILE;
 241        if (ACCEPT_TABLE(dfa)[state] & 0x40000000)
 242                perms.allow |= AA_MAY_ONEXEC;
 243
 244        return perms;
 245}
 246
 247/**
 248 * aa_str_perms - find permission that match @name
 249 * @dfa: to match against  (MAYBE NULL)
 250 * @state: state to start matching in
 251 * @name: string to match against dfa  (NOT NULL)
 252 * @cond: conditions to consider for permission set computation  (NOT NULL)
 253 * @perms: Returns - the permissions found when matching @name
 254 *
 255 * Returns: the final state in @dfa when beginning @start and walking @name
 256 */
 257unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
 258                          const char *name, struct path_cond *cond,
 259                          struct aa_perms *perms)
 260{
 261        unsigned int state;
 262        state = aa_dfa_match(dfa, start, name);
 263        *perms = aa_compute_fperms(dfa, state, cond);
 264
 265        return state;
 266}
 267
 268int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name,
 269                   u32 request, struct path_cond *cond, int flags,
 270                   struct aa_perms *perms)
 271{
 272        int e = 0;
 273
 274        if (profile_unconfined(profile))
 275                return 0;
 276        aa_str_perms(profile->file.dfa, profile->file.start, name, cond, perms);
 277        if (request & ~perms->allow)
 278                e = -EACCES;
 279        return aa_audit_file(profile, perms, op, request, name, NULL, NULL,
 280                             cond->uid, NULL, e);
 281}
 282
 283
 284static int profile_path_perm(const char *op, struct aa_profile *profile,
 285                             const struct path *path, char *buffer, u32 request,
 286                             struct path_cond *cond, int flags,
 287                             struct aa_perms *perms)
 288{
 289        const char *name;
 290        int error;
 291
 292        if (profile_unconfined(profile))
 293                return 0;
 294
 295        error = path_name(op, &profile->label, path,
 296                          flags | profile->path_flags, buffer, &name, cond,
 297                          request);
 298        if (error)
 299                return error;
 300        return __aa_path_perm(op, profile, name, request, cond, flags,
 301                              perms);
 302}
 303
 304/**
 305 * aa_path_perm - do permissions check & audit for @path
 306 * @op: operation being checked
 307 * @label: profile being enforced  (NOT NULL)
 308 * @path: path to check permissions of  (NOT NULL)
 309 * @flags: any additional path flags beyond what the profile specifies
 310 * @request: requested permissions
 311 * @cond: conditional info for this request  (NOT NULL)
 312 *
 313 * Returns: %0 else error if access denied or other error
 314 */
 315int aa_path_perm(const char *op, struct aa_label *label,
 316                 const struct path *path, int flags, u32 request,
 317                 struct path_cond *cond)
 318{
 319        struct aa_perms perms = {};
 320        struct aa_profile *profile;
 321        char *buffer = NULL;
 322        int error;
 323
 324        flags |= PATH_DELEGATE_DELETED | (S_ISDIR(cond->mode) ? PATH_IS_DIR :
 325                                                                0);
 326        buffer = aa_get_buffer(false);
 327        if (!buffer)
 328                return -ENOMEM;
 329        error = fn_for_each_confined(label, profile,
 330                        profile_path_perm(op, profile, path, buffer, request,
 331                                          cond, flags, &perms));
 332
 333        aa_put_buffer(buffer);
 334
 335        return error;
 336}
 337
 338/**
 339 * xindex_is_subset - helper for aa_path_link
 340 * @link: link permission set
 341 * @target: target permission set
 342 *
 343 * test target x permissions are equal OR a subset of link x permissions
 344 * this is done as part of the subset test, where a hardlink must have
 345 * a subset of permissions that the target has.
 346 *
 347 * Returns: true if subset else false
 348 */
 349static inline bool xindex_is_subset(u32 link, u32 target)
 350{
 351        if (((link & ~AA_X_UNSAFE) != (target & ~AA_X_UNSAFE)) ||
 352            ((link & AA_X_UNSAFE) && !(target & AA_X_UNSAFE)))
 353                return false;
 354
 355        return true;
 356}
 357
 358static int profile_path_link(struct aa_profile *profile,
 359                             const struct path *link, char *buffer,
 360                             const struct path *target, char *buffer2,
 361                             struct path_cond *cond)
 362{
 363        const char *lname, *tname = NULL;
 364        struct aa_perms lperms = {}, perms;
 365        const char *info = NULL;
 366        u32 request = AA_MAY_LINK;
 367        unsigned int state;
 368        int error;
 369
 370        error = path_name(OP_LINK, &profile->label, link, profile->path_flags,
 371                          buffer, &lname, cond, AA_MAY_LINK);
 372        if (error)
 373                goto audit;
 374
 375        /* buffer2 freed below, tname is pointer in buffer2 */
 376        error = path_name(OP_LINK, &profile->label, target, profile->path_flags,
 377                          buffer2, &tname, cond, AA_MAY_LINK);
 378        if (error)
 379                goto audit;
 380
 381        error = -EACCES;
 382        /* aa_str_perms - handles the case of the dfa being NULL */
 383        state = aa_str_perms(profile->file.dfa, profile->file.start, lname,
 384                             cond, &lperms);
 385
 386        if (!(lperms.allow & AA_MAY_LINK))
 387                goto audit;
 388
 389        /* test to see if target can be paired with link */
 390        state = aa_dfa_null_transition(profile->file.dfa, state);
 391        aa_str_perms(profile->file.dfa, state, tname, cond, &perms);
 392
 393        /* force audit/quiet masks for link are stored in the second entry
 394         * in the link pair.
 395         */
 396        lperms.audit = perms.audit;
 397        lperms.quiet = perms.quiet;
 398        lperms.kill = perms.kill;
 399
 400        if (!(perms.allow & AA_MAY_LINK)) {
 401                info = "target restricted";
 402                lperms = perms;
 403                goto audit;
 404        }
 405
 406        /* done if link subset test is not required */
 407        if (!(perms.allow & AA_LINK_SUBSET))
 408                goto done_tests;
 409
 410        /* Do link perm subset test requiring allowed permission on link are
 411         * a subset of the allowed permissions on target.
 412         */
 413        aa_str_perms(profile->file.dfa, profile->file.start, tname, cond,
 414                     &perms);
 415
 416        /* AA_MAY_LINK is not considered in the subset test */
 417        request = lperms.allow & ~AA_MAY_LINK;
 418        lperms.allow &= perms.allow | AA_MAY_LINK;
 419
 420        request |= AA_AUDIT_FILE_MASK & (lperms.allow & ~perms.allow);
 421        if (request & ~lperms.allow) {
 422                goto audit;
 423        } else if ((lperms.allow & MAY_EXEC) &&
 424                   !xindex_is_subset(lperms.xindex, perms.xindex)) {
 425                lperms.allow &= ~MAY_EXEC;
 426                request |= MAY_EXEC;
 427                info = "link not subset of target";
 428                goto audit;
 429        }
 430
 431done_tests:
 432        error = 0;
 433
 434audit:
 435        return aa_audit_file(profile, &lperms, OP_LINK, request, lname, tname,
 436                             NULL, cond->uid, info, error);
 437}
 438
 439/**
 440 * aa_path_link - Handle hard link permission check
 441 * @label: the label being enforced  (NOT NULL)
 442 * @old_dentry: the target dentry  (NOT NULL)
 443 * @new_dir: directory the new link will be created in  (NOT NULL)
 444 * @new_dentry: the link being created  (NOT NULL)
 445 *
 446 * Handle the permission test for a link & target pair.  Permission
 447 * is encoded as a pair where the link permission is determined
 448 * first, and if allowed, the target is tested.  The target test
 449 * is done from the point of the link match (not start of DFA)
 450 * making the target permission dependent on the link permission match.
 451 *
 452 * The subset test if required forces that permissions granted
 453 * on link are a subset of the permission granted to target.
 454 *
 455 * Returns: %0 if allowed else error
 456 */
 457int aa_path_link(struct aa_label *label, struct dentry *old_dentry,
 458                 const struct path *new_dir, struct dentry *new_dentry)
 459{
 460        struct path link = { .mnt = new_dir->mnt, .dentry = new_dentry };
 461        struct path target = { .mnt = new_dir->mnt, .dentry = old_dentry };
 462        struct path_cond cond = {
 463                d_backing_inode(old_dentry)->i_uid,
 464                d_backing_inode(old_dentry)->i_mode
 465        };
 466        char *buffer = NULL, *buffer2 = NULL;
 467        struct aa_profile *profile;
 468        int error;
 469
 470        /* buffer freed below, lname is pointer in buffer */
 471        buffer = aa_get_buffer(false);
 472        buffer2 = aa_get_buffer(false);
 473        error = -ENOMEM;
 474        if (!buffer || !buffer2)
 475                goto out;
 476
 477        error = fn_for_each_confined(label, profile,
 478                        profile_path_link(profile, &link, buffer, &target,
 479                                          buffer2, &cond));
 480out:
 481        aa_put_buffer(buffer);
 482        aa_put_buffer(buffer2);
 483        return error;
 484}
 485
 486static void update_file_ctx(struct aa_file_ctx *fctx, struct aa_label *label,
 487                            u32 request)
 488{
 489        struct aa_label *l, *old;
 490
 491        /* update caching of label on file_ctx */
 492        spin_lock(&fctx->lock);
 493        old = rcu_dereference_protected(fctx->label,
 494                                        lockdep_is_held(&fctx->lock));
 495        l = aa_label_merge(old, label, GFP_ATOMIC);
 496        if (l) {
 497                if (l != old) {
 498                        rcu_assign_pointer(fctx->label, l);
 499                        aa_put_label(old);
 500                } else
 501                        aa_put_label(l);
 502                fctx->allow |= request;
 503        }
 504        spin_unlock(&fctx->lock);
 505}
 506
 507static int __file_path_perm(const char *op, struct aa_label *label,
 508                            struct aa_label *flabel, struct file *file,
 509                            u32 request, u32 denied, bool in_atomic)
 510{
 511        struct aa_profile *profile;
 512        struct aa_perms perms = {};
 513        struct path_cond cond = {
 514                .uid = i_uid_into_mnt(file_mnt_user_ns(file), file_inode(file)),
 515                .mode = file_inode(file)->i_mode
 516        };
 517        char *buffer;
 518        int flags, error;
 519
 520        /* revalidation due to label out of date. No revocation at this time */
 521        if (!denied && aa_label_is_subset(flabel, label))
 522                /* TODO: check for revocation on stale profiles */
 523                return 0;
 524
 525        flags = PATH_DELEGATE_DELETED | (S_ISDIR(cond.mode) ? PATH_IS_DIR : 0);
 526        buffer = aa_get_buffer(in_atomic);
 527        if (!buffer)
 528                return -ENOMEM;
 529
 530        /* check every profile in task label not in current cache */
 531        error = fn_for_each_not_in_set(flabel, label, profile,
 532                        profile_path_perm(op, profile, &file->f_path, buffer,
 533                                          request, &cond, flags, &perms));
 534        if (denied && !error) {
 535                /*
 536                 * check every profile in file label that was not tested
 537                 * in the initial check above.
 538                 *
 539                 * TODO: cache full perms so this only happens because of
 540                 * conditionals
 541                 * TODO: don't audit here
 542                 */
 543                if (label == flabel)
 544                        error = fn_for_each(label, profile,
 545                                profile_path_perm(op, profile, &file->f_path,
 546                                                  buffer, request, &cond, flags,
 547                                                  &perms));
 548                else
 549                        error = fn_for_each_not_in_set(label, flabel, profile,
 550                                profile_path_perm(op, profile, &file->f_path,
 551                                                  buffer, request, &cond, flags,
 552                                                  &perms));
 553        }
 554        if (!error)
 555                update_file_ctx(file_ctx(file), label, request);
 556
 557        aa_put_buffer(buffer);
 558
 559        return error;
 560}
 561
 562static int __file_sock_perm(const char *op, struct aa_label *label,
 563                            struct aa_label *flabel, struct file *file,
 564                            u32 request, u32 denied)
 565{
 566        struct socket *sock = (struct socket *) file->private_data;
 567        int error;
 568
 569        AA_BUG(!sock);
 570
 571        /* revalidation due to label out of date. No revocation at this time */
 572        if (!denied && aa_label_is_subset(flabel, label))
 573                return 0;
 574
 575        /* TODO: improve to skip profiles cached in flabel */
 576        error = aa_sock_file_perm(label, op, request, sock);
 577        if (denied) {
 578                /* TODO: improve to skip profiles checked above */
 579                /* check every profile in file label to is cached */
 580                last_error(error, aa_sock_file_perm(flabel, op, request, sock));
 581        }
 582        if (!error)
 583                update_file_ctx(file_ctx(file), label, request);
 584
 585        return error;
 586}
 587
 588/**
 589 * aa_file_perm - do permission revalidation check & audit for @file
 590 * @op: operation being checked
 591 * @label: label being enforced   (NOT NULL)
 592 * @file: file to revalidate access permissions on  (NOT NULL)
 593 * @request: requested permissions
 594 * @in_atomic: whether allocations need to be done in atomic context
 595 *
 596 * Returns: %0 if access allowed else error
 597 */
 598int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
 599                 u32 request, bool in_atomic)
 600{
 601        struct aa_file_ctx *fctx;
 602        struct aa_label *flabel;
 603        u32 denied;
 604        int error = 0;
 605
 606        AA_BUG(!label);
 607        AA_BUG(!file);
 608
 609        fctx = file_ctx(file);
 610
 611        rcu_read_lock();
 612        flabel  = rcu_dereference(fctx->label);
 613        AA_BUG(!flabel);
 614
 615        /* revalidate access, if task is unconfined, or the cached cred
 616         * doesn't match or if the request is for more permissions than
 617         * was granted.
 618         *
 619         * Note: the test for !unconfined(flabel) is to handle file
 620         *       delegation from unconfined tasks
 621         */
 622        denied = request & ~fctx->allow;
 623        if (unconfined(label) || unconfined(flabel) ||
 624            (!denied && aa_label_is_subset(flabel, label))) {
 625                rcu_read_unlock();
 626                goto done;
 627        }
 628
 629        flabel  = aa_get_newest_label(flabel);
 630        rcu_read_unlock();
 631        /* TODO: label cross check */
 632
 633        if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry))
 634                error = __file_path_perm(op, label, flabel, file, request,
 635                                         denied, in_atomic);
 636
 637        else if (S_ISSOCK(file_inode(file)->i_mode))
 638                error = __file_sock_perm(op, label, flabel, file, request,
 639                                         denied);
 640        aa_put_label(flabel);
 641
 642done:
 643        return error;
 644}
 645
 646static void revalidate_tty(struct aa_label *label)
 647{
 648        struct tty_struct *tty;
 649        int drop_tty = 0;
 650
 651        tty = get_current_tty();
 652        if (!tty)
 653                return;
 654
 655        spin_lock(&tty->files_lock);
 656        if (!list_empty(&tty->tty_files)) {
 657                struct tty_file_private *file_priv;
 658                struct file *file;
 659                /* TODO: Revalidate access to controlling tty. */
 660                file_priv = list_first_entry(&tty->tty_files,
 661                                             struct tty_file_private, list);
 662                file = file_priv->file;
 663
 664                if (aa_file_perm(OP_INHERIT, label, file, MAY_READ | MAY_WRITE,
 665                                 IN_ATOMIC))
 666                        drop_tty = 1;
 667        }
 668        spin_unlock(&tty->files_lock);
 669        tty_kref_put(tty);
 670
 671        if (drop_tty)
 672                no_tty();
 673}
 674
 675static int match_file(const void *p, struct file *file, unsigned int fd)
 676{
 677        struct aa_label *label = (struct aa_label *)p;
 678
 679        if (aa_file_perm(OP_INHERIT, label, file, aa_map_file_to_perms(file),
 680                         IN_ATOMIC))
 681                return fd + 1;
 682        return 0;
 683}
 684
 685
 686/* based on selinux's flush_unauthorized_files */
 687void aa_inherit_files(const struct cred *cred, struct files_struct *files)
 688{
 689        struct aa_label *label = aa_get_newest_cred_label(cred);
 690        struct file *devnull = NULL;
 691        unsigned int n;
 692
 693        revalidate_tty(label);
 694
 695        /* Revalidate access to inherited open files. */
 696        n = iterate_fd(files, 0, match_file, label);
 697        if (!n) /* none found? */
 698                goto out;
 699
 700        devnull = dentry_open(&aa_null, O_RDWR, cred);
 701        if (IS_ERR(devnull))
 702                devnull = NULL;
 703        /* replace all the matching ones with this */
 704        do {
 705                replace_fd(n - 1, devnull, 0);
 706        } while ((n = iterate_fd(files, n, match_file, label)) != 0);
 707        if (devnull)
 708                fput(devnull);
 709out:
 710        aa_put_label(label);
 711}
 712