file.c (20089B)
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}