2  * Copyright (c) 2015 Apple Inc. All rights reserved. 
   4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 
   6  * This file contains Original Code and/or Modifications of Original Code 
   7  * as defined in and that are subject to the Apple Public Source License 
   8  * Version 2.0 (the 'License'). You may not use this file except in 
   9  * compliance with the License. The rights granted to you under the License 
  10  * may not be used to create, or enable the creation or redistribution of, 
  11  * unlawful or unlicensed copies of an Apple operating system, or to 
  12  * circumvent, violate, or enable the circumvention or violation of, any 
  13  * terms of an Apple operating system software license agreement. 
  15  * Please obtain a copy of the License at 
  16  * http://www.opensource.apple.com/apsl/ and read it before using this file. 
  18  * The Original Code and all software distributed under the License are 
  19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 
  22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  23  * Please see the License for the specific language governing rights and 
  24  * limitations under the License. 
  26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 
  29 #include <sys/param.h> 
  30 #include <sys/systm.h> 
  31 #include <sys/filedesc.h> 
  32 #include <sys/kernel.h> 
  33 #include <sys/file_internal.h> 
  34 #include <sys/guarded.h> 
  35 #include <kern/kalloc.h> 
  36 #include <sys/sysproto.h> 
  37 #include <sys/vnode.h> 
  38 #include <sys/vnode_internal.h> 
  39 #include <sys/uio_internal.h> 
  40 #include <sys/ubc_internal.h> 
  41 #include <vfs/vfs_support.h> 
  42 #include <security/audit/audit.h> 
  43 #include <sys/syscall.h> 
  44 #include <sys/kauth.h> 
  45 #include <sys/kdebug.h> 
  47 #include <vm/vm_protos.h> 
  49 #include <sys/cprotect.h> 
  53 #define f_flag f_fglob->fg_flag 
  54 #define f_type f_fglob->fg_ops->fo_type 
  55 extern int dofilewrite(vfs_context_t ctx
, struct fileproc 
*fp
, 
  56                          user_addr_t bufp
, user_size_t nbyte
, off_t offset
,  
  57                          int flags
, user_ssize_t 
*retval 
); 
  58 extern int wr_uio(struct proc 
*p
, struct fileproc 
*fp
, uio_t uio
, user_ssize_t 
*retval
); 
  61  * Experimental guarded file descriptor support. 
  64 kern_return_t 
task_exception_notify(exception_type_t exception
, 
  65         mach_exception_data_type_t code
, mach_exception_data_type_t subcode
); 
  68  * Most fd's have an underlying fileproc struct; but some may be 
  69  * guarded_fileproc structs which implement guarded fds.  The latter 
  70  * struct (below) embeds the former. 
  72  * The two types should be distinguished by the "type" portion of f_flags. 
  73  * There's also a magic number to help catch misuse and bugs. 
  75  * This is a bit unpleasant, but results from the desire to allow 
  76  * alternate file behaviours for a few file descriptors without 
  77  * growing the fileproc data structure. 
  80 struct guarded_fileproc 
{ 
  81         struct fileproc gf_fileproc
; 
  90 const size_t sizeof_guarded_fileproc 
= sizeof (struct guarded_fileproc
); 
  92 #define FP_TO_GFP(fp)   ((struct guarded_fileproc *)(fp)) 
  93 #define GFP_TO_FP(gfp)  (&(gfp)->gf_fileproc) 
  95 #define GUARDED_FILEPROC_MAGIC  0x29083 
 102 static struct fileproc 
* 
 103 guarded_fileproc_alloc_init(void *crarg
) 
 105         struct gfp_crarg 
*aarg 
= crarg
; 
 106         struct guarded_fileproc 
*gfp
; 
 108         if ((gfp 
= kalloc(sizeof (*gfp
))) == NULL
) 
 111         bzero(gfp
, sizeof (*gfp
)); 
 112         gfp
->gf_fileproc
.f_flags 
= FTYPE_GUARDED
; 
 113         gfp
->gf_magic 
= GUARDED_FILEPROC_MAGIC
; 
 114         gfp
->gf_guard 
= aarg
->gca_guard
; 
 115         gfp
->gf_attrs 
= aarg
->gca_attrs
; 
 117         return (GFP_TO_FP(gfp
)); 
 121 guarded_fileproc_free(struct fileproc 
*fp
) 
 123         struct guarded_fileproc 
*gfp 
= FP_TO_GFP(fp
); 
 125         if (FILEPROC_TYPE(fp
) != FTYPE_GUARDED 
|| 
 126             GUARDED_FILEPROC_MAGIC 
!= gfp
->gf_magic
) 
 127                 panic("%s: corrupt fp %p flags %x", __func__
, fp
, fp
->f_flags
); 
 129         kfree(gfp
, sizeof (*gfp
)); 
 133 fp_lookup_guarded(proc_t p
, int fd
, guardid_t guard
, 
 134     struct guarded_fileproc 
**gfpp
, int locked
) 
 139         if ((error 
= fp_lookup(p
, fd
, &fp
, locked
)) != 0) 
 141         if (FILEPROC_TYPE(fp
) != FTYPE_GUARDED
) { 
 142                 (void) fp_drop(p
, fd
, fp
, locked
); 
 145         struct guarded_fileproc 
*gfp 
= FP_TO_GFP(fp
); 
 147         if (GUARDED_FILEPROC_MAGIC 
!= gfp
->gf_magic
) 
 148                 panic("%s: corrupt fp %p", __func__
, fp
); 
 150         if (guard 
!= gfp
->gf_guard
) { 
 151                 (void) fp_drop(p
, fd
, fp
, locked
); 
 152                 return (EPERM
); /* *not* a mismatch exception */ 
 160  * Expected use pattern: 
 162  * if (FP_ISGUARDED(fp, GUARD_CLOSE)) { 
 163  *      error = fp_guard_exception(p, fd, fp, kGUARD_EXC_CLOSE); 
 170 fp_isguarded(struct fileproc 
*fp
, u_int attrs
) 
 172         if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) { 
 173                 struct guarded_fileproc 
*gfp 
= FP_TO_GFP(fp
); 
 175                 if (GUARDED_FILEPROC_MAGIC 
!= gfp
->gf_magic
) 
 176                         panic("%s: corrupt gfp %p flags %x", 
 177                             __func__
, gfp
, fp
->f_flags
); 
 178                 return ((attrs 
& gfp
->gf_attrs
) == attrs
); 
 183 extern char *proc_name_address(void *p
); 
 186 fp_guard_exception(proc_t p
, int fd
, struct fileproc 
*fp
, u_int code
) 
 188         if (FILEPROC_TYPE(fp
) != FTYPE_GUARDED
) 
 189                 panic("%s corrupt fp %p flags %x", __func__
, fp
, fp
->f_flags
); 
 191         struct guarded_fileproc 
*gfp 
= FP_TO_GFP(fp
); 
 193         /* all gfd fields protected via proc_fdlock() */ 
 194         proc_fdlock_assert(p
, LCK_MTX_ASSERT_OWNED
); 
 196         if (NULL 
== gfp
->gf_thread
) { 
 197                 thread_t t 
= current_thread(); 
 200                 gfp
->gf_exc_code 
= code
; 
 203                  * This thread was the first to attempt the 
 204                  * operation that violated the guard on this fd; 
 205                  * generate an exception. 
 207                 printf("%s: guarded fd exception: " 
 208                     "fd %d code 0x%x guard 0x%llx\n", 
 209                     proc_name_address(p
), gfp
->gf_exc_fd
, 
 210                     gfp
->gf_exc_code
, gfp
->gf_guard
); 
 212                 thread_guard_violation(t
, GUARD_TYPE_FD
); 
 215                  * We already recorded a violation on this fd for a 
 216                  * different thread, so posting an exception is 
 217                  * already in progress.  We could pause for a bit 
 218                  * and check again, or we could panic (though that seems 
 219                  * heavy handed), or we could just press on with the 
 220                  * error return alone.  For now, resort to printf. 
 222                 printf("%s: guarded fd exception+: " 
 223                     "fd %d code 0x%x guard 0x%llx\n", 
 224                     proc_name_address(p
), gfp
->gf_exc_fd
, 
 225                     gfp
->gf_exc_code
, gfp
->gf_guard
); 
 232  * (Invoked before returning to userland from the syscall handler.) 
 235 fd_guard_ast(thread_t t
) 
 237         proc_t p 
= current_proc(); 
 238         struct filedesc 
*fdp 
= p
->p_fd
; 
 242         for (i 
= fdp
->fd_lastfile
; i 
>= 0; i
--) { 
 243                 struct fileproc 
*fp 
= fdp
->fd_ofiles
[i
]; 
 246                     FILEPROC_TYPE(fp
) != FTYPE_GUARDED
) 
 249                 struct guarded_fileproc 
*gfp 
= FP_TO_GFP(fp
); 
 251                 if (GUARDED_FILEPROC_MAGIC 
!= gfp
->gf_magic
) 
 252                         panic("%s: corrupt gfp %p flags %x", 
 253                             __func__
, gfp
, fp
->f_flags
); 
 255                 if (gfp
->gf_thread 
== t
) { 
 256                         mach_exception_data_type_t code
, subcode
; 
 258                         gfp
->gf_thread 
= NULL
; 
 261                          * EXC_GUARD exception code namespace. 
 264                          * +-------------------------------------------------+ 
 265                          * | [63:61] guard type | [60:0] guard-specific data | 
 266                          * +-------------------------------------------------+ 
 269                          * +-------------------------------------------------+ 
 270                          * |       [63:0] guard-specific data                | 
 271                          * +-------------------------------------------------+ 
 273                          * At the moment, we have just one guard type: file 
 276                          * File descriptor guards use the exception codes like 
 280                          * +--------------------------------------------------+ 
 281                          * |[63:61] GUARD_TYPE_FD | [60:32] flavor | [31:0] fd| 
 282                          * +--------------------------------------------------+ 
 285                          * +--------------------------------------------------+ 
 286                          * |       [63:0] guard value                         | 
 287                          * +--------------------------------------------------+ 
 289                         code 
= (((uint64_t)GUARD_TYPE_FD
) << 61) | 
 290                                (((uint64_t)gfp
->gf_exc_code
) << 32) | 
 291                                ((uint64_t)gfp
->gf_exc_fd
); 
 292                         subcode 
= gfp
->gf_guard
; 
 295                         (void) task_exception_notify(EXC_GUARD
, code
, subcode
); 
 305  * Experimental guarded file descriptor SPIs 
 309  * int guarded_open_np(const char *pathname, int flags, 
 310  *     const guardid_t *guard, u_int guardflags, ...); 
 312  * In this initial implementation, GUARD_DUP must be specified. 
 313  * GUARD_CLOSE, GUARD_SOCKET_IPC and GUARD_FILEPORT are optional. 
 315  * If GUARD_DUP wasn't specified, then we'd have to do the (extra) work 
 316  * to allow dup-ing a descriptor to inherit the guard onto the new 
 317  * descriptor.  (Perhaps GUARD_DUP behaviours should just always be true 
 318  * for a guarded fd?  Or, more sanely, all the dup operations should 
 319  * just always propagate the guard?) 
 321  * Guarded descriptors are always close-on-exec, and GUARD_CLOSE 
 322  * requires close-on-fork; O_CLOEXEC must be set in flags. 
 323  * This setting is immutable; attempts to clear the flag will 
 324  * cause a guard exception. 
 326  * XXX  It's somewhat broken that change_fdguard_np() can completely 
 327  *      remove the guard and thus revoke down the immutability 
 328  *      promises above.  Ick. 
 331 guarded_open_np(proc_t p
, struct guarded_open_np_args 
*uap
, int32_t *retval
) 
 333         if ((uap
->flags 
& O_CLOEXEC
) == 0) 
 336 #define GUARD_REQUIRED (GUARD_DUP) 
 337 #define GUARD_ALL      (GUARD_REQUIRED |        \ 
 338                         (GUARD_CLOSE | GUARD_SOCKET_IPC | GUARD_FILEPORT | GUARD_WRITE)) 
 340         if (((uap
->guardflags 
& GUARD_REQUIRED
) != GUARD_REQUIRED
) || 
 341             ((uap
->guardflags 
& ~GUARD_ALL
) != 0)) 
 345         struct gfp_crarg crarg 
= { 
 346                 .gca_attrs 
= uap
->guardflags
 
 349         if ((error 
= copyin(uap
->guard
, 
 350             &(crarg
.gca_guard
), sizeof (crarg
.gca_guard
))) != 0) 
 354          * Disallow certain guard values -- is zero enough? 
 356         if (crarg
.gca_guard 
== 0) 
 359         struct filedesc 
*fdp 
= p
->p_fd
; 
 360         struct vnode_attr va
; 
 362         vfs_context_t ctx 
= vfs_context_current(); 
 366         cmode 
= ((uap
->mode 
& ~fdp
->fd_cmask
) & ALLPERMS
) & ~S_ISTXT
; 
 367         VATTR_SET(&va
, va_mode
, cmode 
& ACCESSPERMS
); 
 369         NDINIT(&nd
, LOOKUP
, OP_OPEN
, FOLLOW 
| AUDITVNPATH1
, UIO_USERSPACE
, 
 372         return (open1(ctx
, &nd
, uap
->flags 
| O_CLOFORK
, &va
, 
 373             guarded_fileproc_alloc_init
, &crarg
, retval
)); 
 377  * int guarded_open_dprotected_np(const char *pathname, int flags, 
 378  *     const guardid_t *guard, u_int guardflags, int dpclass, int dpflags, ...); 
 380  * This SPI is extension of guarded_open_np() to include dataprotection class on creation 
 381  * in "dpclass" and dataprotection flags 'dpflags'. Otherwise behaviors are same as in 
 385 guarded_open_dprotected_np(proc_t p
, struct guarded_open_dprotected_np_args 
*uap
, int32_t *retval
) 
 387         if ((uap
->flags 
& O_CLOEXEC
) == 0) 
 390         if (((uap
->guardflags 
& GUARD_REQUIRED
) != GUARD_REQUIRED
) || 
 391             ((uap
->guardflags 
& ~GUARD_ALL
) != 0)) 
 395         struct gfp_crarg crarg 
= { 
 396                 .gca_attrs 
= uap
->guardflags
 
 399         if ((error 
= copyin(uap
->guard
, 
 400             &(crarg
.gca_guard
), sizeof (crarg
.gca_guard
))) != 0) 
 404          * Disallow certain guard values -- is zero enough? 
 406         if (crarg
.gca_guard 
== 0) 
 409         struct filedesc 
*fdp 
= p
->p_fd
; 
 410         struct vnode_attr va
; 
 412         vfs_context_t ctx 
= vfs_context_current(); 
 416         cmode 
= ((uap
->mode 
& ~fdp
->fd_cmask
) & ALLPERMS
) & ~S_ISTXT
; 
 417         VATTR_SET(&va
, va_mode
, cmode 
& ACCESSPERMS
); 
 419         NDINIT(&nd
, LOOKUP
, OP_OPEN
, FOLLOW 
| AUDITVNPATH1
, UIO_USERSPACE
, 
 423          * Initialize the extra fields in vnode_attr to pass down dataprotection  
 425          * 1. target cprotect class. 
 426          * 2. set a flag to mark it as requiring open-raw-encrypted semantics.  
 428         if (uap
->flags 
& O_CREAT
) {      
 429                 VATTR_SET(&va
, va_dataprotect_class
, uap
->dpclass
); 
 432         if (uap
->dpflags 
& (O_DP_GETRAWENCRYPTED
|O_DP_GETRAWUNENCRYPTED
)) { 
 433                 if ( uap
->flags 
& (O_RDWR 
| O_WRONLY
)) { 
 434                         /* Not allowed to write raw encrypted bytes */ 
 437                 if (uap
->dpflags 
& O_DP_GETRAWENCRYPTED
) { 
 438                     VATTR_SET(&va
, va_dataprotect_flags
, VA_DP_RAWENCRYPTED
); 
 440                 if (uap
->dpflags 
& O_DP_GETRAWUNENCRYPTED
) { 
 441                     VATTR_SET(&va
, va_dataprotect_flags
, VA_DP_RAWUNENCRYPTED
); 
 445         return (open1(ctx
, &nd
, uap
->flags 
| O_CLOFORK
, &va
, 
 446             guarded_fileproc_alloc_init
, &crarg
, retval
)); 
 450  * int guarded_kqueue_np(const guardid_t *guard, u_int guardflags); 
 452  * Create a guarded kqueue descriptor with guardid and guardflags. 
 454  * Same restrictions on guardflags as for guarded_open_np(). 
 455  * All kqueues are -always- close-on-exec and close-on-fork by themselves 
 456  * and are not sendable. 
 459 guarded_kqueue_np(proc_t p
, struct guarded_kqueue_np_args 
*uap
, int32_t *retval
) 
 461         if (((uap
->guardflags 
& GUARD_REQUIRED
) != GUARD_REQUIRED
) || 
 462             ((uap
->guardflags 
& ~GUARD_ALL
) != 0)) 
 466         struct gfp_crarg crarg 
= { 
 467                 .gca_attrs 
= uap
->guardflags
 
 470         if ((error 
= copyin(uap
->guard
, 
 471             &(crarg
.gca_guard
), sizeof (crarg
.gca_guard
))) != 0) 
 474         if (crarg
.gca_guard 
== 0) 
 477         return (kqueue_body(p
, guarded_fileproc_alloc_init
, &crarg
, retval
)); 
 481  * int guarded_close_np(int fd, const guardid_t *guard); 
 484 guarded_close_np(proc_t p
, struct guarded_close_np_args 
*uap
, 
 485     __unused 
int32_t *retval
) 
 487         struct guarded_fileproc 
*gfp
; 
 492         AUDIT_SYSCLOSE(p
, fd
); 
 494         if ((error 
= copyin(uap
->guard
, &uguard
, sizeof (uguard
))) != 0) 
 498         if ((error 
= fp_lookup_guarded(p
, fd
, uguard
, &gfp
, 1)) != 0) { 
 502         error 
= close_internal_locked(p
, fd
, GFP_TO_FP(gfp
), 0); 
 509  * change_fdguard_np(int fd, const guardid_t *guard, u_int guardflags, 
 510  *    const guardid_t *nguard, u_int nguardflags, int *fdflagsp); 
 512  * Given a file descriptor, atomically exchange <guard, guardflags> for 
 513  * a new guard <nguard, nguardflags>, returning the previous fd 
 514  * flags (see fcntl:F_SETFD) in *fdflagsp. 
 516  * This syscall can be used to either (a) add a new guard to an existing 
 517  * unguarded file descriptor (b) remove the old guard from an existing 
 518  * guarded file descriptor or (c) change the guard (guardid and/or 
 519  * guardflags) on a guarded file descriptor. 
 521  * If 'guard' is NULL, fd must be unguarded at entry. If the call completes 
 522  * successfully the fd will be guarded with <nguard, nguardflags>. 
 524  * Guarding a file descriptor has some side-effects on the "fdflags" 
 525  * associated with the descriptor - in particular FD_CLOEXEC is 
 526  * forced ON unconditionally, and FD_CLOFORK is forced ON by GUARD_CLOSE. 
 527  * Callers who wish to subsequently restore the state of the fd should save 
 528  * the value of *fdflagsp after a successful invocation. 
 530  * If 'nguard' is NULL, fd must be guarded at entry, <guard, guardflags> 
 531  * must match with what's already guarding the descriptor, and the 
 532  * result will be to completely remove the guard.  Note also that the 
 533  * fdflags are copied to the descriptor from the incoming *fdflagsp argument.  
 535  * If the descriptor is guarded, and neither 'guard' nor 'nguard' is NULL 
 536  * and <guard, guardflags> matches what's already guarding the descriptor, 
 537  * then <nguard, nguardflags> becomes the new guard.  In this case, even if 
 538  * the GUARD_CLOSE flag is being cleared, it is still possible to continue 
 539  * to keep FD_CLOFORK on the descriptor by passing FD_CLOFORK via fdflagsp. 
 541  * (File descriptors whose underlying fileglobs are marked FG_CONFINED are 
 542  * still close-on-fork, regardless of the setting of FD_CLOFORK.) 
 544  * Example 1: Guard an unguarded descriptor during a set of operations, 
 545  * then restore the original state of the descriptor. 
 548  * change_fdguard_np(fd, NULL, 0, &myguard, GUARD_CLOSE, &sav_flags); 
 549  * // do things with now guarded 'fd' 
 550  * change_fdguard_np(fd, &myguard, GUARD_CLOSE, NULL, 0, &sav_flags); 
 551  * // fd now unguarded. 
 553  * Example 2: Change the guard of a guarded descriptor during a set of 
 554  * operations, then restore the original state of the descriptor. 
 556  * int sav_flags = (gdflags & GUARD_CLOSE) ? FD_CLOFORK : 0; 
 557  * change_fdguard_np(fd, &gd, gdflags, &myguard, GUARD_CLOSE, &sav_flags); 
 558  * // do things with 'fd' with a different guard 
 559  * change_fdguard_np(fd, &myg, GUARD_CLOSE, &gd, gdflags, &sav_flags); 
 560  * // back to original guarded state 
 562  * XXX  This SPI is too much of a chainsaw and should be revised. 
 566 change_fdguard_np(proc_t p
, struct change_fdguard_np_args 
*uap
, 
 567     __unused 
int32_t *retval
) 
 572         guardid_t oldg 
= 0, newg 
= 0; 
 575         if (0 != uap
->guard 
&& 
 576             0 != (error 
= copyin(uap
->guard
, &oldg
, sizeof (oldg
)))) 
 577                 return (error
); /* can't copyin current guard */ 
 579         if (0 != uap
->nguard 
&& 
 580             0 != (error 
= copyin(uap
->nguard
, &newg
, sizeof (newg
)))) 
 581                 return (error
); /* can't copyin new guard */ 
 583         if (0 != uap
->fdflagsp 
&& 
 584             0 != (error 
= copyin(uap
->fdflagsp
, &nfdflags
, sizeof (nfdflags
)))) 
 585                 return (error
); /* can't copyin new fdflags */ 
 589         if ((error 
= fp_lookup(p
, fd
, &fp
, 1)) != 0) { 
 594         if (0 != uap
->fdflagsp
) { 
 595                 int ofdflags 
= FDFLAGS_GET(p
, fd
); 
 596                 int ofl 
= ((ofdflags 
& UF_EXCLOSE
) ? FD_CLOEXEC 
: 0) | 
 597                         ((ofdflags 
& UF_FORKCLOSE
) ? FD_CLOFORK 
: 0); 
 599                 if (0 != (error 
= copyout(&ofl
, uap
->fdflagsp
, sizeof (ofl
)))) { 
 601                         goto dropout
; /* can't copyout old fdflags */ 
 606         if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) { 
 607                 if (0 == uap
->guard 
|| 0 == uap
->guardflags
) 
 608                         error 
= EINVAL
; /* missing guard! */ 
 610                         error 
= EPERM
; /* guardids cannot be zero */ 
 612                 if (0 != uap
->guard 
|| 0 != uap
->guardflags
) 
 613                         error 
= EINVAL
; /* guard provided, but none needed! */ 
 619         if (0 != uap
->nguard
) { 
 621                  * There's a new guard in town. 
 624                         error 
= EINVAL
; /* guards cannot contain zero */ 
 625                 else if (((uap
->nguardflags 
& GUARD_REQUIRED
) != GUARD_REQUIRED
) || 
 626                     ((uap
->nguardflags 
& ~GUARD_ALL
) != 0)) 
 627                         error 
= EINVAL
; /* must have valid attributes too */ 
 631                 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) { 
 633                          * Replace old guard with new guard 
 635                         struct guarded_fileproc 
*gfp 
= FP_TO_GFP(fp
); 
 637                         if (GUARDED_FILEPROC_MAGIC 
!= gfp
->gf_magic
) 
 638                                 panic("%s: corrupt gfp %p flags %x", 
 639                                       __func__
, gfp
, fp
->f_flags
); 
 641                         if (oldg 
== gfp
->gf_guard 
&& 
 642                             uap
->guardflags 
== gfp
->gf_attrs
) { 
 644                                  * Must match existing guard + attributes 
 645                                  * before we'll swap them to new ones, managing 
 646                                  * fdflags "side-effects" as we go.   Note that 
 647                                  * userland can request FD_CLOFORK semantics. 
 649                                 if (gfp
->gf_attrs 
& GUARD_CLOSE
) 
 650                                         FDFLAGS_CLR(p
, fd
, UF_FORKCLOSE
); 
 651                                 gfp
->gf_guard 
= newg
; 
 652                                 gfp
->gf_attrs 
= uap
->nguardflags
; 
 653                                 if (gfp
->gf_attrs 
& GUARD_CLOSE
) 
 654                                         FDFLAGS_SET(p
, fd
, UF_FORKCLOSE
); 
 656                                     (nfdflags 
& FD_CLOFORK
) ? UF_FORKCLOSE 
: 0); 
 657                                 /* FG_CONFINED enforced regardless */ 
 664                          * Add a guard to a previously unguarded descriptor 
 666                         switch (FILEGLOB_DTYPE(fp
->f_fglob
)) { 
 679                         struct gfp_crarg crarg 
= { 
 681                                 .gca_attrs 
= uap
->nguardflags
 
 683                         struct fileproc 
*nfp 
= 
 684                                 guarded_fileproc_alloc_init(&crarg
); 
 685                         struct guarded_fileproc 
*gfp
; 
 689                         switch (error 
= fp_tryswap(p
, fd
, nfp
)) { 
 690                         case 0: /* guarded-ness comes with side-effects */ 
 691                                 gfp 
= FP_TO_GFP(nfp
); 
 692                                 if (gfp
->gf_attrs 
& GUARD_CLOSE
) 
 693                                         FDFLAGS_SET(p
, fd
, UF_FORKCLOSE
); 
 694                                 FDFLAGS_SET(p
, fd
, UF_EXCLOSE
); 
 695                                 (void) fp_drop(p
, fd
, nfp
, 1); 
 698                         case EKEEPLOOKING
: /* f_iocount indicates a collision */ 
 699                                 (void) fp_drop(p
, fd
, fp
, 1); 
 703                                 (void) fp_drop(p
, fd
, fp
, 1); 
 714                 if (FILEPROC_TYPE(fp
) == FTYPE_GUARDED
) { 
 716                          * Remove the guard altogether. 
 718                         struct guarded_fileproc 
*gfp 
= FP_TO_GFP(fp
); 
 720                         if (0 != uap
->nguardflags
) { 
 725                         if (GUARDED_FILEPROC_MAGIC 
!= gfp
->gf_magic
) 
 726                                 panic("%s: corrupt gfp %p flags %x", 
 727                                       __func__
, gfp
, fp
->f_flags
); 
 729                         if (oldg 
!= gfp
->gf_guard 
|| 
 730                             uap
->guardflags 
!= gfp
->gf_attrs
) { 
 736                         struct fileproc 
*nfp 
= fileproc_alloc_init(NULL
); 
 739                         switch (error 
= fp_tryswap(p
, fd
, nfp
)) { 
 740                         case 0: /* undo side-effects of guarded-ness */ 
 741                                 FDFLAGS_CLR(p
, fd
, UF_FORKCLOSE 
| UF_EXCLOSE
); 
 743                                     (nfdflags 
& FD_CLOFORK
) ? UF_FORKCLOSE 
: 0); 
 744                                 /* FG_CONFINED enforced regardless */ 
 746                                     (nfdflags 
& FD_CLOEXEC
) ? UF_EXCLOSE 
: 0); 
 747                                 (void) fp_drop(p
, fd
, nfp
, 1); 
 750                         case EKEEPLOOKING
: /* f_iocount indicates collision */ 
 751                                 (void) fp_drop(p
, fd
, fp
, 1); 
 755                                 (void) fp_drop(p
, fd
, fp
, 1); 
 763                          * Not already guarded, and no new guard? 
 770         (void) fp_drop(p
, fd
, fp
, 1); 
 776  * user_ssize_t guarded_write_np(int fd, const guardid_t *guard, 
 777  *                          user_addr_t cbuf, user_ssize_t nbyte); 
 779  * Initial implementation of guarded writes. 
 782 guarded_write_np(struct proc 
*p
, struct guarded_write_np_args 
*uap
, user_ssize_t 
*retval
) 
 788         struct guarded_fileproc 
*gfp
; 
 789         bool wrote_some 
= false; 
 793         if ((error 
= copyin(uap
->guard
, &uguard
, sizeof (uguard
))) != 0) 
 796         error 
= fp_lookup_guarded(p
, fd
, uguard
, &gfp
, 0); 
 801         if ((fp
->f_flag 
& FWRITE
) == 0) { 
 805                 struct vfs_context context 
= *(vfs_context_current()); 
 806                 context
.vc_ucred 
= fp
->f_fglob
->fg_cred
; 
 808                 error 
= dofilewrite(&context
, fp
, uap
->cbuf
, uap
->nbyte
, 
 809                         (off_t
)-1, 0, retval
); 
 810                 wrote_some 
= *retval 
> 0; 
 813                 fp_drop_written(p
, fd
, fp
); 
 815                 fp_drop(p
, fd
, fp
, 0); 
 820  * user_ssize_t guarded_pwrite_np(int fd, const guardid_t *guard, 
 821  *                        user_addr_t buf, user_size_t nbyte, off_t offset); 
 823  * Initial implementation of guarded pwrites. 
 826  guarded_pwrite_np(struct proc 
*p
, struct guarded_pwrite_np_args 
*uap
, user_ssize_t 
*retval
) 
 831         vnode_t vp  
= (vnode_t
)0; 
 833         struct guarded_fileproc 
*gfp
; 
 834         bool wrote_some 
= false; 
 838         if ((error 
= copyin(uap
->guard
, &uguard
, sizeof (uguard
))) != 0) 
 841         error 
= fp_lookup_guarded(p
, fd
, uguard
, &gfp
, 0); 
 846         if ((fp
->f_flag 
& FWRITE
) == 0) { 
 849                 struct vfs_context context 
= *vfs_context_current(); 
 850                 context
.vc_ucred 
= fp
->f_fglob
->fg_cred
; 
 852                 if (fp
->f_type 
!= DTYPE_VNODE
) { 
 856                 vp 
= (vnode_t
)fp
->f_fglob
->fg_data
; 
 857                 if (vnode_isfifo(vp
)) { 
 861                 if ((vp
->v_flag 
& VISTTY
)) { 
 865                 if (uap
->offset 
== (off_t
)-1) { 
 870                 error 
= dofilewrite(&context
, fp
, uap
->buf
, uap
->nbyte
, 
 871                         uap
->offset
, FOF_OFFSET
, retval
); 
 872                 wrote_some 
= *retval 
> 0; 
 876                 fp_drop_written(p
, fd
, fp
); 
 878                 fp_drop(p
, fd
, fp
, 0); 
 880         KERNEL_DEBUG_CONSTANT((BSDDBG_CODE(DBG_BSD_SC_EXTENDED_INFO
, SYS_guarded_pwrite_np
) | DBG_FUNC_NONE
), 
 881               uap
->fd
, uap
->nbyte
, (unsigned int)((uap
->offset 
>> 32)), (unsigned int)(uap
->offset
), 0); 
 887  * user_ssize_t guarded_writev_np(int fd, const guardid_t *guard, 
 888  *                                   struct iovec *iovp, u_int iovcnt); 
 890  * Initial implementation of guarded writev. 
 894 guarded_writev_np(struct proc 
*p
, struct guarded_writev_np_args 
*uap
, user_ssize_t 
*retval
) 
 899         struct user_iovec 
*iovp
; 
 901         struct guarded_fileproc 
*gfp
; 
 902         bool wrote_some 
= false; 
 904         AUDIT_ARG(fd
, uap
->fd
); 
 906         /* Verify range bedfore calling uio_create() */ 
 907         if (uap
->iovcnt 
<= 0 || uap
->iovcnt 
> UIO_MAXIOV
) 
 910         /* allocate a uio large enough to hold the number of iovecs passed */ 
 911         auio 
= uio_create(uap
->iovcnt
, 0, 
 912                                   (IS_64BIT_PROCESS(p
) ? UIO_USERSPACE64 
: UIO_USERSPACE32
), 
 915         /* get location of iovecs within the uio.  then copyin the iovecs from 
 918         iovp 
= uio_iovsaddr(auio
); 
 921                 goto ExitThisRoutine
; 
 923         error 
= copyin_user_iovec_array(uap
->iovp
, 
 924                 IS_64BIT_PROCESS(p
) ? UIO_USERSPACE64 
: UIO_USERSPACE32
, 
 927                 goto ExitThisRoutine
; 
 930         /* finalize uio_t for use and do the IO  
 932         error 
= uio_calculateresid(auio
); 
 934                 goto ExitThisRoutine
; 
 937         if ((error 
= copyin(uap
->guard
, &uguard
, sizeof (uguard
))) != 0) 
 938                 goto ExitThisRoutine
; 
 940         error 
= fp_lookup_guarded(p
, uap
->fd
, uguard
, &gfp
, 0); 
 942                 goto ExitThisRoutine
; 
 945         if ((fp
->f_flag 
& FWRITE
) == 0) { 
 948                 error 
= wr_uio(p
, fp
, auio
, retval
); 
 949                 wrote_some 
= *retval 
> 0; 
 953                 fp_drop_written(p
, uap
->fd
, fp
); 
 955                 fp_drop(p
, uap
->fd
, fp
, 0);