The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/kern/kern_descrip.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000-2010 Apple Inc. All rights reserved.
    3  *
    4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
    5  * 
    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.
   14  * 
   15  * Please obtain a copy of the License at
   16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
   17  * 
   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.
   25  * 
   26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
   27  */
   28 /* Copyright (c) 1995, 1997 Apple Computer, Inc. All Rights Reserved */
   29 /*
   30  * Copyright (c) 1982, 1986, 1989, 1991, 1993
   31  *      The Regents of the University of California.  All rights reserved.
   32  * (c) UNIX System Laboratories, Inc.
   33  * All or some portions of this file are derived from material licensed
   34  * to the University of California by American Telephone and Telegraph
   35  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
   36  * the permission of UNIX System Laboratories, Inc.
   37  *
   38  * Redistribution and use in source and binary forms, with or without
   39  * modification, are permitted provided that the following conditions
   40  * are met:
   41  * 1. Redistributions of source code must retain the above copyright
   42  *    notice, this list of conditions and the following disclaimer.
   43  * 2. Redistributions in binary form must reproduce the above copyright
   44  *    notice, this list of conditions and the following disclaimer in the
   45  *    documentation and/or other materials provided with the distribution.
   46  * 3. All advertising materials mentioning features or use of this software
   47  *    must display the following acknowledgement:
   48  *      This product includes software developed by the University of
   49  *      California, Berkeley and its contributors.
   50  * 4. Neither the name of the University nor the names of its contributors
   51  *    may be used to endorse or promote products derived from this software
   52  *    without specific prior written permission.
   53  *
   54  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   55  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   56  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   57  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   58  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   59  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   60  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   61  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   62  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   63  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   64  * SUCH DAMAGE.
   65  *
   66  *      @(#)kern_descrip.c      8.8 (Berkeley) 2/14/95
   67  */
   68 /*
   69  * NOTICE: This file was modified by SPARTA, Inc. in 2006 to introduce
   70  * support for mandatory and extensible security protections.  This notice
   71  * is included in support of clause 2.2 (b) of the Apple Public License,
   72  * Version 2.0.
   73  */
   74 
   75 #include <sys/param.h>
   76 #include <sys/systm.h>
   77 #include <sys/filedesc.h>
   78 #include <sys/kernel.h>
   79 #include <sys/vnode_internal.h>
   80 #include <sys/proc_internal.h>
   81 #include <sys/kauth.h>
   82 #include <sys/file_internal.h>
   83 #include <sys/socket.h>
   84 #include <sys/socketvar.h>
   85 #include <sys/stat.h>
   86 #include <sys/ioctl.h>
   87 #include <sys/fcntl.h>
   88 #include <sys/malloc.h>
   89 #include <sys/mman.h>
   90 #include <sys/syslog.h>
   91 #include <sys/unistd.h>
   92 #include <sys/resourcevar.h>
   93 #include <sys/aio_kern.h>
   94 #include <sys/ev.h>
   95 #include <kern/lock.h>
   96 #include <sys/uio_internal.h>
   97 
   98 #include <security/audit/audit.h>
   99 
  100 #include <sys/mount_internal.h>
  101 #include <sys/kdebug.h>
  102 #include <sys/sysproto.h>
  103 #include <sys/pipe.h>
  104 #include <sys/spawn.h>
  105 #include <kern/kern_types.h>
  106 #include <kern/kalloc.h>
  107 #include <libkern/OSAtomic.h>
  108 
  109 #include <sys/ubc_internal.h>
  110 
  111 #include <kern/ipc_misc.h>
  112 #include <vm/vm_protos.h>
  113 
  114 #include <mach/mach_port.h>
  115 
  116 #if CONFIG_PROTECT
  117 #include <sys/cprotect.h>
  118 #endif
  119 #include <hfs/hfs.h>
  120 
  121 kern_return_t ipc_object_copyin(ipc_space_t, mach_port_name_t,
  122     mach_msg_type_name_t, ipc_port_t *);
  123 void ipc_port_release_send(ipc_port_t);
  124 
  125 struct psemnode;
  126 struct pshmnode;
  127 
  128 static int finishdup(proc_t p,
  129     struct filedesc *fdp, int old, int new, int flags, int32_t *retval);
  130 
  131 int falloc_locked(proc_t p, struct fileproc **resultfp, int *resultfd, vfs_context_t ctx, int locked);
  132 void fg_drop(struct fileproc * fp);
  133 void fg_free(struct fileglob *fg);
  134 void fg_ref(struct fileproc * fp);
  135 void fileport_releasefg(struct fileglob *fg);
  136 
  137 /* flags for close_internal_locked */
  138 #define FD_DUP2RESV 1
  139 static int close_internal_locked(struct proc *p, int fd, struct fileproc *fp, int flags);
  140 
  141 static int closef_finish(struct fileproc *fp, struct fileglob *fg, proc_t p, vfs_context_t ctx);
  142 
  143 /* We don't want these exported */
  144 __private_extern__
  145 int open1(vfs_context_t, struct nameidata *, int, struct vnode_attr *, int32_t *);
  146 
  147 __private_extern__
  148 int unlink1(vfs_context_t, struct nameidata *, int);
  149 
  150 static void _fdrelse(struct proc * p, int fd);
  151 
  152 
  153 extern void file_lock_init(void) __attribute__((section("__TEXT, initcode")));
  154 extern int kqueue_stat(struct fileproc *fp, void *ub, int isstat4, proc_t p);
  155 #if SOCKETS
  156 extern int soo_stat(struct socket *so, void *ub, int isstat64);
  157 #endif /* SOCKETS */
  158 
  159 extern kauth_scope_t    kauth_scope_fileop;
  160 
  161 extern int cs_debug;
  162 
  163 /* Conflict wait queue for when selects collide (opaque type) */
  164 extern struct wait_queue select_conflict_queue;
  165 
  166 #define f_flag f_fglob->fg_flag
  167 #define f_type f_fglob->fg_type
  168 #define f_msgcount f_fglob->fg_msgcount
  169 #define f_cred f_fglob->fg_cred
  170 #define f_ops f_fglob->fg_ops
  171 #define f_offset f_fglob->fg_offset
  172 #define f_data f_fglob->fg_data
  173 /*
  174  * Descriptor management.
  175  */
  176 struct fmsglist fmsghead;       /* head of list of open files */
  177 struct fmsglist fmsg_ithead;    /* head of list of open files */
  178 int nfiles;                     /* actual number of open files */
  179 
  180 
  181 lck_grp_attr_t * file_lck_grp_attr;
  182 lck_grp_t * file_lck_grp;
  183 lck_attr_t * file_lck_attr;
  184 
  185 lck_mtx_t * uipc_lock;
  186 
  187 
  188 /*
  189  * file_lock_init
  190  *
  191  * Description: Initialize the file lock group and the uipc and flist locks
  192  *
  193  * Parameters:  (void)
  194  *
  195  * Returns:     void
  196  *
  197  * Notes:       Called at system startup from bsd_init().
  198  */
  199 void
  200 file_lock_init(void)
  201 {
  202         /* allocate file lock group attribute and group */
  203         file_lck_grp_attr= lck_grp_attr_alloc_init();
  204 
  205         file_lck_grp = lck_grp_alloc_init("file",  file_lck_grp_attr);
  206 
  207         /* Allocate file lock attribute */
  208         file_lck_attr = lck_attr_alloc_init();
  209 
  210         uipc_lock = lck_mtx_alloc_init(file_lck_grp, file_lck_attr);
  211 }
  212 
  213 
  214 /*
  215  * proc_fdlock, proc_fdlock_spin
  216  *
  217  * Description: Lock to control access to the per process struct fileproc
  218  *              and struct filedesc
  219  *
  220  * Parameters:  p                               Process to take the lock on
  221  *
  222  * Returns:     void
  223  *
  224  * Notes:       The lock is initialized in forkproc() and destroyed in
  225  *              reap_child_process().
  226  */
  227 void
  228 proc_fdlock(proc_t p)
  229 {
  230         lck_mtx_lock(&p->p_fdmlock);
  231 }
  232 
  233 void
  234 proc_fdlock_spin(proc_t p)
  235 {
  236         lck_mtx_lock_spin(&p->p_fdmlock);
  237 }
  238 
  239 void
  240 proc_fdlock_assert(proc_t p, int assertflags)
  241 {
  242         lck_mtx_assert(&p->p_fdmlock, assertflags);
  243 }
  244 
  245 
  246 /*
  247  * proc_fdunlock
  248  *
  249  * Description: Unlock the lock previously locked by a call to proc_fdlock()
  250  *
  251  * Parameters:  p                               Process to drop the lock on
  252  *
  253  * Returns:     void
  254  */
  255 void
  256 proc_fdunlock(proc_t p)
  257 {
  258         lck_mtx_unlock(&p->p_fdmlock);
  259 }
  260 
  261 
  262 /*
  263  * System calls on descriptors.
  264  */
  265 
  266 
  267 /*
  268  * getdtablesize
  269  *
  270  * Description: Returns the per process maximum size of the descriptor table
  271  *
  272  * Parameters:  p                               Process being queried
  273  *              retval                          Pointer to the call return area
  274  *
  275  * Returns:     0                               Success
  276  *
  277  * Implicit returns:
  278  *              *retval (modified)              Size of dtable
  279  */
  280 int
  281 getdtablesize(proc_t p, __unused struct getdtablesize_args *uap, int32_t *retval)
  282 {
  283         proc_fdlock_spin(p);
  284         *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
  285         proc_fdunlock(p);
  286 
  287         return (0);
  288 }
  289 
  290 
  291 void
  292 procfdtbl_reservefd(struct proc * p, int fd)
  293 {
  294         p->p_fd->fd_ofiles[fd] = NULL;
  295         p->p_fd->fd_ofileflags[fd] |= UF_RESERVED;
  296 }
  297 
  298 void
  299 procfdtbl_markclosefd(struct proc * p, int fd)
  300 {
  301         p->p_fd->fd_ofileflags[fd] |= (UF_RESERVED | UF_CLOSING);
  302 }
  303 
  304 void
  305 procfdtbl_releasefd(struct proc * p, int fd, struct fileproc * fp)
  306 {
  307         if (fp != NULL)
  308                 p->p_fd->fd_ofiles[fd] = fp;
  309         p->p_fd->fd_ofileflags[fd] &= ~UF_RESERVED;
  310         if ((p->p_fd->fd_ofileflags[fd] & UF_RESVWAIT) == UF_RESVWAIT) {
  311                 p->p_fd->fd_ofileflags[fd] &= ~UF_RESVWAIT;
  312                 wakeup(&p->p_fd);
  313         }
  314 }
  315 
  316 void 
  317 procfdtbl_waitfd(struct proc * p, int fd)
  318 {
  319         p->p_fd->fd_ofileflags[fd] |= UF_RESVWAIT;
  320         msleep(&p->p_fd, &p->p_fdmlock, PRIBIO, "ftbl_waitfd", NULL);
  321 }
  322 
  323 
  324 void
  325 procfdtbl_clearfd(struct proc * p, int fd)
  326 {
  327         int waiting;
  328 
  329         waiting = (p->p_fd->fd_ofileflags[fd] & UF_RESVWAIT);
  330         p->p_fd->fd_ofiles[fd] = NULL;       
  331         p->p_fd->fd_ofileflags[fd] = 0;
  332         if ( waiting == UF_RESVWAIT) {
  333                 wakeup(&p->p_fd);
  334         }
  335 }
  336 
  337 /*
  338  * _fdrelse
  339  *
  340  * Description: Inline utility function to free an fd in a filedesc
  341  *
  342  * Parameters:  fdp                             Pointer to filedesc fd lies in
  343  *              fd                              fd to free
  344  *              reserv                          fd should be reserved
  345  *
  346  * Returns:     void
  347  *
  348  * Locks:       Assumes proc_fdlock for process pointing to fdp is held by
  349  *              the caller
  350  */
  351 static void
  352 _fdrelse(struct proc * p, int fd)
  353 {
  354         struct filedesc *fdp = p->p_fd;
  355         int nfd = 0;
  356 
  357         if (fd < fdp->fd_freefile)
  358                 fdp->fd_freefile = fd;
  359 #if DIAGNOSTIC
  360         if (fd > fdp->fd_lastfile)
  361                 panic("fdrelse: fd_lastfile inconsistent");
  362 #endif
  363         procfdtbl_clearfd(p, fd);
  364 
  365         while ((nfd = fdp->fd_lastfile) > 0 &&
  366                         fdp->fd_ofiles[nfd] == NULL &&
  367                         !(fdp->fd_ofileflags[nfd] & UF_RESERVED))
  368                 fdp->fd_lastfile--;
  369 }
  370 
  371 
  372 int
  373 fd_rdwr(
  374         int fd,
  375         enum uio_rw rw,
  376         uint64_t base,
  377         int64_t len,
  378         enum uio_seg segflg,
  379         off_t   offset,
  380         int     io_flg,
  381         int64_t *aresid)
  382 {
  383         struct fileproc *fp;
  384         proc_t  p;
  385         int error = 0;
  386         int flags = 0;
  387         int spacetype;
  388         uio_t auio = NULL;
  389         char uio_buf[ UIO_SIZEOF(1) ];
  390         struct vfs_context context = *(vfs_context_current());
  391 
  392         p = current_proc();
  393 
  394         error = fp_lookup(p, fd, &fp, 0);
  395         if (error)
  396                 return(error);
  397 
  398         if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_PIPE && fp->f_type != DTYPE_SOCKET) {
  399                 error = EINVAL;
  400                 goto out;
  401         }
  402         if (rw == UIO_WRITE && !(fp->f_flag & FWRITE)) {
  403                 error = EBADF;
  404                 goto out;
  405         }
  406         
  407         if (rw == UIO_READ && !(fp->f_flag & FREAD)) {
  408                 error = EBADF;
  409                 goto out;
  410         }
  411         
  412         context.vc_ucred = fp->f_fglob->fg_cred;
  413 
  414         if (UIO_SEG_IS_USER_SPACE(segflg))
  415                 spacetype = proc_is64bit(p) ? UIO_USERSPACE64 : UIO_USERSPACE32;
  416         else
  417                 spacetype = UIO_SYSSPACE;
  418 
  419         auio = uio_createwithbuffer(1, offset, spacetype, rw, &uio_buf[0], sizeof(uio_buf));
  420 
  421         uio_addiov(auio, base, len);
  422 
  423         if ( !(io_flg & IO_APPEND))
  424                 flags = FOF_OFFSET;
  425 
  426         if (rw == UIO_WRITE)
  427                 error = fo_write(fp, auio, flags, &context);
  428         else
  429                 error = fo_read(fp, auio, flags, &context);
  430 
  431         if (aresid)
  432                 *aresid = uio_resid(auio);
  433         else {
  434                 if (uio_resid(auio) && error == 0)
  435                         error = EIO;
  436         }
  437 out:
  438         if (rw == UIO_WRITE && error == 0)
  439                 fp_drop_written(p, fd, fp);
  440         else
  441                 fp_drop(p, fd, fp, 0);
  442 
  443         return error;
  444 }
  445 
  446 
  447 
  448 /*
  449  * dup
  450  *
  451  * Description: Duplicate a file descriptor.
  452  *
  453  * Parameters:  p                               Process performing the dup
  454  *              uap->fd                         The fd to dup
  455  *              retval                          Pointer to the call return area
  456  *
  457  * Returns:     0                               Success
  458  *              !0                              Errno
  459  *
  460  * Implicit returns:
  461  *              *retval (modified)              The new descriptor
  462  */
  463 int
  464 dup(proc_t p, struct dup_args *uap, int32_t *retval)
  465 {
  466         struct filedesc *fdp = p->p_fd;
  467         int old = uap->fd;
  468         int new, error;
  469         struct fileproc *fp;
  470 
  471         proc_fdlock(p);
  472         if ( (error = fp_lookup(p, old, &fp, 1)) ) {
  473                 proc_fdunlock(p);
  474                 return(error);
  475         }
  476         if ( (error = fdalloc(p, 0, &new)) ) {
  477                 fp_drop(p, old, fp, 1);
  478                 proc_fdunlock(p);
  479                 return (error);
  480         }
  481         error = finishdup(p, fdp, old, new, 0, retval);
  482         fp_drop(p, old, fp, 1);
  483         proc_fdunlock(p);
  484 
  485         return (error);
  486 }
  487 
  488 /*
  489  * dup2
  490  *
  491  * Description: Duplicate a file descriptor to a particular value.
  492  *
  493  * Parameters:  p                               Process performing the dup
  494  *              uap->from                       The fd to dup
  495  *              uap->to                         The fd to dup it to
  496  *              retval                          Pointer to the call return area
  497  *
  498  * Returns:     0                               Success
  499  *              !0                              Errno
  500  *
  501  * Implicit returns:
  502  *              *retval (modified)              The new descriptor
  503  */
  504 int
  505 dup2(proc_t p, struct dup2_args *uap, int32_t *retval)
  506 {
  507         struct filedesc *fdp = p->p_fd;
  508         int old = uap->from, new = uap->to;
  509         int i, error;
  510         struct fileproc *fp, *nfp;
  511 
  512         proc_fdlock(p);
  513 
  514 startover:
  515         if ( (error = fp_lookup(p, old, &fp, 1)) ) {
  516                 proc_fdunlock(p);
  517                 return(error);
  518         }
  519         if (new < 0 ||
  520                 (rlim_t)new >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
  521             new >= maxfiles) {
  522                 fp_drop(p, old, fp, 1);
  523                 proc_fdunlock(p);
  524                 return (EBADF);
  525         }
  526         if (old == new) {
  527                 fp_drop(p, old, fp, 1);
  528                 *retval = new;
  529                 proc_fdunlock(p);
  530                 return (0);
  531         }
  532         if (new < 0 || new >= fdp->fd_nfiles) {
  533                 if ( (error = fdalloc(p, new, &i)) ) {
  534                         fp_drop(p, old, fp, 1);
  535                         proc_fdunlock(p);
  536                         return (error);
  537                 }
  538                 if (new != i) {
  539                         fdrelse(p, i);
  540                         goto closeit;
  541                 }
  542         } else {
  543 closeit:
  544                 while ((fdp->fd_ofileflags[new] & UF_RESERVED) == UF_RESERVED)  {
  545                                 fp_drop(p, old, fp, 1);
  546                                 procfdtbl_waitfd(p, new);
  547 #if DIAGNOSTIC
  548                                 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
  549 #endif
  550                                 goto startover;
  551                 }
  552 
  553                 if ((fdp->fd_ofiles[new] != NULL) &&
  554                     ((error = fp_lookup(p, new, &nfp, 1)) == 0)) {
  555                         fp_drop(p, old, fp, 1);
  556                         (void)close_internal_locked(p, new, nfp, FD_DUP2RESV);
  557 #if DIAGNOSTIC
  558                         proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
  559 #endif
  560                         procfdtbl_clearfd(p, new);
  561                         goto startover;
  562                 } else  {
  563 #if DIAGNOSTIC
  564                         if (fdp->fd_ofiles[new] != NULL)
  565                                 panic("dup2: no ref on fileproc %d", new);
  566 #endif
  567                         procfdtbl_reservefd(p, new);
  568                 }
  569 
  570 #if DIAGNOSTIC
  571                 proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
  572 #endif
  573 
  574         }
  575 #if DIAGNOSTIC
  576         if (fdp->fd_ofiles[new] != 0)
  577                 panic("dup2: overwriting fd_ofiles with new %d", new);
  578         if ((fdp->fd_ofileflags[new] & UF_RESERVED) == 0)
  579                 panic("dup2: unreserved fileflags with new %d", new);
  580 #endif
  581         error = finishdup(p, fdp, old, new, 0, retval);
  582         fp_drop(p, old, fp, 1);
  583         proc_fdunlock(p);
  584 
  585         return(error);
  586 }
  587 
  588 
  589 /*
  590  * fcntl
  591  *
  592  * Description: The file control system call.
  593  *
  594  * Parameters:  p                               Process performing the fcntl
  595  *              uap->fd                         The fd to operate against
  596  *              uap->cmd                        The command to perform
  597  *              uap->arg                        Pointer to the command argument
  598  *              retval                          Pointer to the call return area
  599  *
  600  * Returns:     0                               Success
  601  *              !0                              Errno (see fcntl_nocancel)
  602  *
  603  * Implicit returns:
  604  *              *retval (modified)              fcntl return value (if any)
  605  *
  606  * Notes:       This system call differs from fcntl_nocancel() in that it
  607  *              tests for cancellation prior to performing a potentially
  608  *              blocking operation.
  609  */
  610 int
  611 fcntl(proc_t p, struct fcntl_args *uap, int32_t *retval)
  612 {
  613         __pthread_testcancel(1);
  614         return(fcntl_nocancel(p, (struct fcntl_nocancel_args *)uap, retval));
  615 }
  616 
  617 
  618 /*
  619  * fcntl_nocancel
  620  *
  621  * Description: A non-cancel-testing file control system call.
  622  *
  623  * Parameters:  p                               Process performing the fcntl
  624  *              uap->fd                         The fd to operate against
  625  *              uap->cmd                        The command to perform
  626  *              uap->arg                        Pointer to the command argument
  627  *              retval                          Pointer to the call return area
  628  *
  629  * Returns:     0                               Success
  630  *              EINVAL
  631  *      fp_lookup:EBADF                         Bad file descriptor
  632  * [F_DUPFD]
  633  *      fdalloc:EMFILE
  634  *      fdalloc:ENOMEM
  635  *      finishdup:EBADF
  636  *      finishdup:ENOMEM
  637  * [F_SETOWN]
  638  *              ESRCH
  639  * [F_SETLK]
  640  *              EBADF
  641  *              EOVERFLOW
  642  *      copyin:EFAULT
  643  *      vnode_getwithref:???
  644  *      VNOP_ADVLOCK:???
  645  * [F_GETLK]
  646  *              EBADF
  647  *              EOVERFLOW
  648  *      copyin:EFAULT
  649  *      copyout:EFAULT
  650  *      vnode_getwithref:???
  651  *      VNOP_ADVLOCK:???
  652  * [F_PREALLOCATE]
  653  *              EBADF
  654  *              EINVAL
  655  *      copyin:EFAULT
  656  *      copyout:EFAULT
  657  *      vnode_getwithref:???
  658  *      VNOP_ALLOCATE:???
  659  * [F_SETSIZE,F_RDADVISE]
  660  *              EBADF
  661  *      copyin:EFAULT
  662  *      vnode_getwithref:???
  663  * [F_RDAHEAD,F_NOCACHE]
  664  *              EBADF
  665  *      vnode_getwithref:???
  666  * [???]
  667  *
  668  * Implicit returns:
  669  *              *retval (modified)              fcntl return value (if any)
  670  */
  671 int
  672 fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, int32_t *retval)
  673 {
  674         int fd = uap->fd;
  675         struct filedesc *fdp = p->p_fd;
  676         struct fileproc *fp;
  677         char *pop;
  678         struct vnode *vp = NULLVP;      /* for AUDIT_ARG() at end */
  679         int i, tmp, error, error2, flg = F_POSIX;
  680         struct flock fl;
  681         struct vfs_context context;
  682         off_t offset;
  683         int newmin;
  684         daddr64_t lbn, bn;
  685         unsigned int fflag;
  686         user_addr_t argp;
  687         boolean_t is64bit;
  688 
  689         AUDIT_ARG(fd, uap->fd);
  690         AUDIT_ARG(cmd, uap->cmd);
  691 
  692         proc_fdlock(p);
  693         if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
  694                 proc_fdunlock(p);
  695                 return(error);
  696         }
  697         context.vc_thread = current_thread();
  698         context.vc_ucred = fp->f_cred;
  699 
  700         is64bit = proc_is64bit(p);
  701         if (is64bit) {
  702                 argp = uap->arg;
  703         }
  704         else {
  705                 /*
  706                  * Since the arg parameter is defined as a long but may be
  707                  * either a long or a pointer we must take care to handle
  708                  * sign extension issues.  Our sys call munger will sign
  709                  * extend a long when we are called from a 32-bit process.
  710                  * Since we can never have an address greater than 32-bits
  711                  * from a 32-bit process we lop off the top 32-bits to avoid
  712                  * getting the wrong address
  713                  */
  714                 argp = CAST_USER_ADDR_T((uint32_t)uap->arg);
  715         }
  716 
  717         pop = &fdp->fd_ofileflags[fd];
  718 
  719 #if CONFIG_MACF
  720         error = mac_file_check_fcntl(proc_ucred(p), fp->f_fglob, uap->cmd,
  721             uap->arg);
  722         if (error)
  723                 goto out;
  724 #endif
  725 
  726         switch (uap->cmd) {
  727 
  728         case F_DUPFD:
  729         case F_DUPFD_CLOEXEC:
  730                 newmin = CAST_DOWN_EXPLICIT(int, uap->arg); /* arg is an int, so we won't lose bits */
  731                 AUDIT_ARG(value32, newmin);
  732                 if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
  733                     newmin >= maxfiles) {
  734                         error = EINVAL;
  735                         goto out;
  736                 }
  737                 if ( (error = fdalloc(p, newmin, &i)) )
  738                         goto out;
  739                 error = finishdup(p, fdp, fd, i,
  740                     uap->cmd == F_DUPFD_CLOEXEC ? UF_EXCLOSE : 0, retval);
  741                 goto out;
  742 
  743         case F_GETFD:
  744                 *retval = (*pop & UF_EXCLOSE)? 1 : 0;
  745                 error = 0;
  746                 goto out;
  747 
  748         case F_SETFD:
  749                 AUDIT_ARG(value32, uap->arg);
  750                 *pop = (*pop &~ UF_EXCLOSE) |
  751                         (uap->arg & 1)? UF_EXCLOSE : 0;
  752                 error = 0;
  753                 goto out;
  754 
  755         case F_GETFL:
  756                 *retval = OFLAGS(fp->f_flag);
  757                 error = 0;
  758                 goto out;
  759 
  760         case F_SETFL:
  761                 fp->f_flag &= ~FCNTLFLAGS;
  762                 tmp = CAST_DOWN_EXPLICIT(int, uap->arg); /* arg is an int, so we won't lose bits */
  763                 AUDIT_ARG(value32, tmp);
  764                 fp->f_flag |= FFLAGS(tmp) & FCNTLFLAGS;
  765                 tmp = fp->f_flag & FNONBLOCK;
  766                 error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, &context);
  767                 if (error)
  768                         goto out;
  769                 tmp = fp->f_flag & FASYNC;
  770                 error = fo_ioctl(fp, FIOASYNC, (caddr_t)&tmp, &context);
  771                 if (!error)
  772                         goto out;
  773                 fp->f_flag &= ~FNONBLOCK;
  774                 tmp = 0;
  775                 (void)fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, &context);
  776                 goto out;
  777 
  778         case F_GETOWN:
  779                 if (fp->f_type == DTYPE_SOCKET) {
  780                         *retval = ((struct socket *)fp->f_data)->so_pgid;
  781                         error = 0;
  782                         goto out;
  783                 }
  784                 error = fo_ioctl(fp, (int)TIOCGPGRP, (caddr_t)retval, &context);
  785                 *retval = -*retval;
  786                 goto out;
  787 
  788         case F_SETOWN:
  789                 tmp = CAST_DOWN_EXPLICIT(pid_t, uap->arg); /* arg is an int, so we won't lose bits */
  790                 AUDIT_ARG(value32, tmp);
  791                 if (fp->f_type == DTYPE_SOCKET) {
  792                         ((struct socket *)fp->f_data)->so_pgid = tmp;
  793                         error =0;
  794                         goto out;
  795                 }
  796                 if (fp->f_type == DTYPE_PIPE) {
  797                         error =  fo_ioctl(fp, TIOCSPGRP, (caddr_t)&tmp, &context);
  798                         goto out;
  799                 }
  800 
  801                 if (tmp <= 0) {
  802                         tmp = -tmp;
  803                 } else {
  804                         proc_t p1 = proc_find(tmp);
  805                         if (p1 == 0) {
  806                                 error = ESRCH;
  807                                 goto out;
  808                         }
  809                         tmp = (int)p1->p_pgrpid;
  810                         proc_rele(p1);
  811                 }
  812                 error =  fo_ioctl(fp, (int)TIOCSPGRP, (caddr_t)&tmp, &context);
  813                 goto out;
  814 
  815         case F_SETNOSIGPIPE:
  816                 tmp = CAST_DOWN_EXPLICIT(int, uap->arg);
  817                 if (fp->f_type == DTYPE_SOCKET) {
  818                         error = sock_setsockopt((struct socket *)fp->f_data,
  819                             SOL_SOCKET, SO_NOSIGPIPE, &tmp, sizeof (tmp));
  820                 } else {
  821                         struct fileglob *fg = fp->f_fglob;
  822 
  823                         lck_mtx_lock_spin(&fg->fg_lock);
  824                         if (tmp)
  825                                 fg->fg_lflags |= FG_NOSIGPIPE;
  826                         else
  827                                 fg->fg_lflags &= FG_NOSIGPIPE;
  828                         lck_mtx_unlock(&fg->fg_lock);
  829                         error = 0;
  830                 }
  831                 goto out;
  832 
  833         case F_GETNOSIGPIPE:
  834                 if (fp->f_type == DTYPE_SOCKET) {
  835                         int retsize = sizeof (*retval);
  836                         error = sock_getsockopt((struct socket *)fp->f_data,
  837                             SOL_SOCKET, SO_NOSIGPIPE, retval, &retsize);
  838                 } else {
  839                         *retval = (fp->f_fglob->fg_lflags & FG_NOSIGPIPE) ?
  840                                 1 : 0;
  841                         error = 0;
  842                 }
  843                 goto out;
  844 
  845         case F_SETLKW:
  846                 flg |= F_WAIT;
  847                 /* Fall into F_SETLK */
  848 
  849         case F_SETLK:
  850                 if (fp->f_type != DTYPE_VNODE) {
  851                         error = EBADF;
  852                         goto out;
  853                 }
  854                 vp = (struct vnode *)fp->f_data;
  855 
  856                 fflag = fp->f_flag;
  857                 offset = fp->f_offset;
  858                 proc_fdunlock(p);
  859 
  860                 /* Copy in the lock structure */
  861                 error = copyin(argp, (caddr_t)&fl, sizeof(fl));
  862                 if (error) {
  863                         goto outdrop;
  864                 }
  865 
  866                 volatile off_t affected_lock_area_set = 0;
  867                 affected_lock_area_set = fl.l_start + offset;
  868                 if ((fl.l_whence == SEEK_CUR) && (affected_lock_area_set < fl.l_start)) {
  869                     error = EOVERFLOW;
  870                     goto outdrop;
  871                 }
  872 
  873                 if ( (error = vnode_getwithref(vp)) ) {
  874                         goto outdrop;
  875                 }
  876                 if (fl.l_whence == SEEK_CUR)
  877                         fl.l_start += offset;
  878 
  879 #if CONFIG_MACF
  880                 error = mac_file_check_lock(proc_ucred(p), fp->f_fglob,
  881                     F_SETLK, &fl);
  882                 if (error) {
  883                         (void)vnode_put(vp);
  884                         goto outdrop;
  885                 }
  886 #endif
  887                 switch (fl.l_type) {
  888 
  889                 case F_RDLCK:
  890                         if ((fflag & FREAD) == 0) {
  891                                 (void)vnode_put(vp);
  892                                 error = EBADF;
  893                                 goto outdrop;
  894                         }
  895                         // XXX UInt32 unsafe for LP64 kernel
  896                         OSBitOrAtomic(P_LADVLOCK, &p->p_ladvflag);
  897                         error = VNOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg, &context);
  898                         (void)vnode_put(vp);
  899                         goto outdrop;
  900 
  901                 case F_WRLCK:
  902                         if ((fflag & FWRITE) == 0) {
  903                                 (void)vnode_put(vp);
  904                                 error = EBADF;
  905                                 goto outdrop;
  906                         }
  907                         // XXX UInt32 unsafe for LP64 kernel
  908                         OSBitOrAtomic(P_LADVLOCK, &p->p_ladvflag);
  909                         error = VNOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg, &context);
  910                         (void)vnode_put(vp);
  911                         goto outdrop;
  912 
  913                 case F_UNLCK:
  914                         error = VNOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &fl,
  915                                 F_POSIX, &context);
  916                         (void)vnode_put(vp);
  917                         goto outdrop;
  918 
  919                 default:
  920                         (void)vnode_put(vp);
  921                         error = EINVAL;
  922                         goto outdrop;
  923                 }
  924 
  925         case F_GETLK:
  926 #if CONFIG_EMBEDDED
  927         case F_GETLKPID:
  928 #endif
  929                 if (fp->f_type != DTYPE_VNODE) {
  930                         error = EBADF;
  931                         goto out;
  932                 }
  933                 vp = (struct vnode *)fp->f_data;
  934 
  935                 offset = fp->f_offset;
  936                 proc_fdunlock(p);
  937 
  938                 /* Copy in the lock structure */
  939                 error = copyin(argp, (caddr_t)&fl, sizeof(fl));
  940                 if (error)
  941                         goto outdrop;
  942 
  943                 volatile off_t affected_lock_area_end = 0;
  944                 affected_lock_area_end = fl.l_start + offset;
  945                 /* Check starting byte and ending byte for EOVERFLOW in SEEK_CUR */
  946                 /* and ending byte for EOVERFLOW in SEEK_SET */
  947                 if (((fl.l_whence == SEEK_CUR) && 
  948                      ((affected_lock_area_end < fl.l_start) ||
  949                       ((fl.l_len > 0) && (affected_lock_area_end + fl.l_len - 1 < affected_lock_area_end)))) ||
  950                     ((fl.l_whence == SEEK_SET) && (fl.l_len > 0) && (fl.l_start + fl.l_len - 1 < fl.l_start)))
  951                 {
  952                         /* lf_advlock doesn't check start/end for F_GETLK if file has no locks */
  953                         error = EOVERFLOW;
  954                         goto outdrop;
  955                 }
  956 
  957                 if ((fl.l_whence == SEEK_SET) && (fl.l_start < 0)) {
  958                         error = EINVAL;
  959                         goto outdrop;
  960                 }
  961 
  962                 switch (fl.l_type) {
  963                 case F_RDLCK:
  964                 case F_UNLCK:
  965                 case F_WRLCK:
  966                         break;
  967                 default:
  968                         error = EINVAL;
  969                         goto outdrop;
  970                 }
  971 
  972                 switch (fl.l_whence) {
  973                 case SEEK_CUR:
  974                 case SEEK_SET:
  975                 case SEEK_END:
  976                         break;
  977                 default:
  978                         error = EINVAL;
  979                         goto outdrop;
  980                 }
  981 
  982                 if ( (error = vnode_getwithref(vp)) == 0 ) {
  983                         if (fl.l_whence == SEEK_CUR)
  984                                 fl.l_start += offset;
  985 
  986 #if CONFIG_MACF
  987                         error = mac_file_check_lock(proc_ucred(p), fp->f_fglob,
  988                             uap->cmd, &fl);
  989                         if (error == 0)
  990 #endif
  991                         error = VNOP_ADVLOCK(vp, (caddr_t)p, uap->cmd, &fl, F_POSIX, &context);
  992 
  993                         (void)vnode_put(vp);
  994 
  995                         if (error == 0)
  996                                 error = copyout((caddr_t)&fl, argp, sizeof(fl));
  997                 }
  998                 goto outdrop;
  999 
 1000         case F_PREALLOCATE: {
 1001                 fstore_t alloc_struct;    /* structure for allocate command */
 1002                 u_int32_t alloc_flags = 0;
 1003 
 1004                 if (fp->f_type != DTYPE_VNODE) {
 1005                         error = EBADF;
 1006                         goto out;
 1007                 }
 1008 
 1009                 vp = (struct vnode *)fp->f_data;
 1010                 proc_fdunlock(p);
 1011 
 1012                 /* make sure that we have write permission */
 1013                 if ((fp->f_flag & FWRITE) == 0) {
 1014                         error = EBADF;
 1015                         goto outdrop;
 1016                 }
 1017 
 1018                 error = copyin(argp, (caddr_t)&alloc_struct, sizeof(alloc_struct));
 1019                 if (error)
 1020                         goto outdrop;
 1021 
 1022                 /* now set the space allocated to 0 */
 1023                 alloc_struct.fst_bytesalloc = 0;
 1024                 
 1025                 /*
 1026                  * Do some simple parameter checking
 1027                  */
 1028 
 1029                 /* set up the flags */
 1030 
 1031                 alloc_flags |= PREALLOCATE;
 1032                 
 1033                 if (alloc_struct.fst_flags & F_ALLOCATECONTIG)
 1034                         alloc_flags |= ALLOCATECONTIG;
 1035 
 1036                 if (alloc_struct.fst_flags & F_ALLOCATEALL)
 1037                         alloc_flags |= ALLOCATEALL;
 1038 
 1039                 /*
 1040                  * Do any position mode specific stuff.  The only
 1041                  * position mode  supported now is PEOFPOSMODE
 1042                  */
 1043 
 1044                 switch (alloc_struct.fst_posmode) {
 1045         
 1046                 case F_PEOFPOSMODE:
 1047                         if (alloc_struct.fst_offset != 0) {
 1048                                 error = EINVAL;
 1049                                 goto outdrop;
 1050                         }
 1051 
 1052                         alloc_flags |= ALLOCATEFROMPEOF;
 1053                         break;
 1054 
 1055                 case F_VOLPOSMODE:
 1056                         if (alloc_struct.fst_offset <= 0) {
 1057                                 error = EINVAL;
 1058                                 goto outdrop;
 1059                         }
 1060 
 1061                         alloc_flags |= ALLOCATEFROMVOL;
 1062                         break;
 1063 
 1064                 default: {
 1065                         error = EINVAL;
 1066                         goto outdrop;
 1067                         }
 1068                 }
 1069                 if ( (error = vnode_getwithref(vp)) == 0 ) {
 1070                         /*
 1071                          * call allocate to get the space
 1072                          */
 1073                         error = VNOP_ALLOCATE(vp,alloc_struct.fst_length,alloc_flags,
 1074                                               &alloc_struct.fst_bytesalloc, alloc_struct.fst_offset,
 1075                                               &context);
 1076                         (void)vnode_put(vp);
 1077 
 1078                         error2 = copyout((caddr_t)&alloc_struct, argp, sizeof(alloc_struct));
 1079 
 1080                         if (error == 0)
 1081                                 error = error2;
 1082                 }
 1083                 goto outdrop;
 1084                 
 1085                 }
 1086         case F_SETSIZE:
 1087                 if (fp->f_type != DTYPE_VNODE) {
 1088                         error = EBADF;
 1089                         goto out;
 1090                 }
 1091                 vp = (struct vnode *)fp->f_data;
 1092                 proc_fdunlock(p);
 1093 
 1094                 error = copyin(argp, (caddr_t)&offset, sizeof (off_t));
 1095                 if (error)
 1096                         goto outdrop;
 1097                 AUDIT_ARG(value64, offset);
 1098 
 1099                 error = vnode_getwithref(vp);
 1100                 if (error)
 1101                         goto outdrop;
 1102 
 1103 #if CONFIG_MACF
 1104                 error = mac_vnode_check_truncate(&context,
 1105                     fp->f_fglob->fg_cred, vp);
 1106                 if (error) {
 1107                         (void)vnode_put(vp);
 1108                         goto outdrop;
 1109                 }
 1110 #endif
 1111                 /*
 1112                  * Make sure that we are root.  Growing a file
 1113                  * without zero filling the data is a security hole 
 1114                  * root would have access anyway so we'll allow it
 1115                  */
 1116                 if (!is_suser()) {
 1117                         error = EACCES;
 1118                 } else {
 1119                         /*
 1120                          * set the file size
 1121                          */
 1122                         error = vnode_setsize(vp, offset, IO_NOZEROFILL,
 1123                             &context);
 1124                 }
 1125 
 1126                 (void)vnode_put(vp);
 1127                 goto outdrop;
 1128 
 1129         case F_RDAHEAD:
 1130                 if (fp->f_type != DTYPE_VNODE) {
 1131                         error = EBADF;
 1132                         goto out;
 1133                 }
 1134                 if (uap->arg)
 1135                         fp->f_fglob->fg_flag &= ~FNORDAHEAD;
 1136                 else
 1137                         fp->f_fglob->fg_flag |= FNORDAHEAD;
 1138 
 1139                 goto out;
 1140 
 1141         case F_NOCACHE:
 1142                 if (fp->f_type != DTYPE_VNODE) {
 1143                         error = EBADF;
 1144                         goto out;
 1145                 }
 1146                 if (uap->arg)
 1147                         fp->f_fglob->fg_flag |= FNOCACHE;
 1148                 else
 1149                         fp->f_fglob->fg_flag &= ~FNOCACHE;
 1150 
 1151                 goto out;
 1152 
 1153         case F_NODIRECT:
 1154                 if (fp->f_type != DTYPE_VNODE) {
 1155                         error = EBADF;
 1156                         goto out;
 1157                 }
 1158                 if (uap->arg)
 1159                         fp->f_fglob->fg_flag |= FNODIRECT;
 1160                 else
 1161                         fp->f_fglob->fg_flag &= ~FNODIRECT;
 1162 
 1163                 goto out;
 1164 
 1165         case F_SINGLE_WRITER:
 1166                 if (fp->f_type != DTYPE_VNODE) {
 1167                         error = EBADF;
 1168                         goto out;
 1169                 }
 1170                 if (uap->arg)
 1171                         fp->f_fglob->fg_flag |= FSINGLE_WRITER;
 1172                 else
 1173                         fp->f_fglob->fg_flag &= ~FSINGLE_WRITER;
 1174 
 1175                 goto out;
 1176 
 1177         case F_GLOBAL_NOCACHE:
 1178                 if (fp->f_type != DTYPE_VNODE) {
 1179                         error = EBADF;
 1180                         goto out;
 1181                 }
 1182                 vp = (struct vnode *)fp->f_data;
 1183                 proc_fdunlock(p);
 1184 
 1185                 if ( (error = vnode_getwithref(vp)) == 0 ) {
 1186 
 1187                         *retval = vnode_isnocache(vp);
 1188 
 1189                         if (uap->arg)
 1190                                 vnode_setnocache(vp);
 1191                         else
 1192                                 vnode_clearnocache(vp);
 1193 
 1194                         (void)vnode_put(vp);
 1195                 }
 1196                 goto outdrop;
 1197 
 1198         case F_CHECK_OPENEVT:
 1199                 if (fp->f_type != DTYPE_VNODE) {
 1200                         error = EBADF;
 1201                         goto out;
 1202                 }
 1203                 vp = (struct vnode *)fp->f_data;
 1204                 proc_fdunlock(p);
 1205 
 1206                 if ( (error = vnode_getwithref(vp)) == 0 ) {
 1207 
 1208                         *retval = vnode_is_openevt(vp);
 1209 
 1210                         if (uap->arg)
 1211                                 vnode_set_openevt(vp);
 1212                         else
 1213                                 vnode_clear_openevt(vp);
 1214 
 1215                         (void)vnode_put(vp);
 1216                 }
 1217                 goto outdrop;
 1218 
 1219         case F_RDADVISE: {
 1220                 struct radvisory ra_struct;
 1221 
 1222                 if (fp->f_type != DTYPE_VNODE) {
 1223                         error = EBADF;
 1224                         goto out;
 1225                 }
 1226                 vp = (struct vnode *)fp->f_data;
 1227                 proc_fdunlock(p);
 1228 
 1229                 if ( (error = copyin(argp, (caddr_t)&ra_struct, sizeof(ra_struct))) )
 1230                         goto outdrop;
 1231                 if ( (error = vnode_getwithref(vp)) == 0 ) {
 1232                         error = VNOP_IOCTL(vp, F_RDADVISE, (caddr_t)&ra_struct, 0, &context);
 1233 
 1234                         (void)vnode_put(vp);
 1235                 }
 1236                 goto outdrop;
 1237                 }
 1238 
 1239         case F_FLUSH_DATA:
 1240 
 1241                 if (fp->f_type != DTYPE_VNODE) {
 1242                         error = EBADF;
 1243                         goto out;
 1244                 }
 1245                 vp = (struct vnode *)fp->f_data;
 1246                 proc_fdunlock(p);
 1247 
 1248                 if ( (error = vnode_getwithref(vp)) == 0 ) {
 1249                         error = cluster_push(vp, 0);
 1250 
 1251                         (void)vnode_put(vp);
 1252                 }
 1253                 goto outdrop;
 1254 
 1255         case F_LOG2PHYS:
 1256         case F_LOG2PHYS_EXT: {
 1257                 struct log2phys l2p_struct;    /* structure for allocate command */
 1258                 int devBlockSize;
 1259 
 1260                 off_t file_offset = 0;
 1261                 size_t a_size = 0;
 1262                 size_t run = 0;
 1263 
 1264                 if (uap->cmd == F_LOG2PHYS_EXT) {
 1265                         error = copyin(argp, (caddr_t)&l2p_struct, sizeof(l2p_struct));
 1266                         if (error)
 1267                                 goto out;
 1268                         file_offset = l2p_struct.l2p_devoffset;
 1269                 } else {
 1270                         file_offset = fp->f_offset;
 1271                 }
 1272                 if (fp->f_type != DTYPE_VNODE) {
 1273                         error = EBADF;
 1274                         goto out;
 1275                 }
 1276                 vp = (struct vnode *)fp->f_data;
 1277                 proc_fdunlock(p);
 1278                 if ( (error = vnode_getwithref(vp)) ) {
 1279                         goto outdrop;
 1280                 }
 1281                 error = VNOP_OFFTOBLK(vp, file_offset, &lbn);
 1282                 if (error) {
 1283                         (void)vnode_put(vp);
 1284                         goto outdrop;
 1285                 }
 1286                 error = VNOP_BLKTOOFF(vp, lbn, &offset);
 1287                 if (error) {
 1288                         (void)vnode_put(vp);
 1289                         goto outdrop;
 1290                 }
 1291                 devBlockSize = vfs_devblocksize(vnode_mount(vp));
 1292                 if (uap->cmd == F_LOG2PHYS_EXT) {
 1293                         a_size = l2p_struct.l2p_contigbytes;
 1294                 } else {
 1295                         a_size = devBlockSize;
 1296                 }
 1297                 
 1298                 error = VNOP_BLOCKMAP(vp, offset, a_size, &bn, &run, NULL, 0, &context);
 1299 
 1300                 (void)vnode_put(vp);
 1301 
 1302                 if (!error) {
 1303                         l2p_struct.l2p_flags = 0;       /* for now */
 1304                         if (uap->cmd == F_LOG2PHYS_EXT) {
 1305                                 l2p_struct.l2p_contigbytes = run - (file_offset - offset);
 1306                         } else {
 1307                                 l2p_struct.l2p_contigbytes = 0; /* for now */
 1308                         }
 1309                         l2p_struct.l2p_devoffset = bn * devBlockSize;
 1310                         l2p_struct.l2p_devoffset += file_offset - offset;
 1311                         error = copyout((caddr_t)&l2p_struct, argp, sizeof(l2p_struct));
 1312                 }
 1313                 goto outdrop;
 1314                 }
 1315         case F_GETPATH: {
 1316                 char *pathbufp;
 1317                 int pathlen;
 1318 
 1319                 if (fp->f_type != DTYPE_VNODE) {
 1320                         error = EBADF;
 1321                         goto out;
 1322                 }
 1323                 vp = (struct vnode *)fp->f_data;
 1324                 proc_fdunlock(p);
 1325 
 1326                 pathlen = MAXPATHLEN;
 1327                 MALLOC(pathbufp, char *, pathlen, M_TEMP, M_WAITOK);
 1328                 if (pathbufp == NULL) {
 1329                         error = ENOMEM;
 1330                         goto outdrop;
 1331                 }
 1332                 if ( (error = vnode_getwithref(vp)) == 0 ) {
 1333                         error = vn_getpath(vp, pathbufp, &pathlen);
 1334                         (void)vnode_put(vp);
 1335 
 1336                         if (error == 0)
 1337                                 error = copyout((caddr_t)pathbufp, argp, pathlen);
 1338                 }
 1339                 FREE(pathbufp, M_TEMP);
 1340                 goto outdrop;
 1341         }
 1342 
 1343         case F_PATHPKG_CHECK: {
 1344                 char *pathbufp;
 1345                 size_t pathlen;
 1346 
 1347                 if (fp->f_type != DTYPE_VNODE) {
 1348                         error = EBADF;
 1349                         goto out;
 1350                 }
 1351                 vp = (struct vnode *)fp->f_data;
 1352                 proc_fdunlock(p);
 1353 
 1354                 pathlen = MAXPATHLEN;
 1355                 pathbufp = kalloc(MAXPATHLEN);
 1356 
 1357                 if ( (error = copyinstr(argp, pathbufp, MAXPATHLEN, &pathlen)) == 0 ) {
 1358                         if ( (error = vnode_getwithref(vp)) == 0 ) {
 1359                                 AUDIT_ARG(text, pathbufp);
 1360                                 error = vn_path_package_check(vp, pathbufp, pathlen, retval);
 1361 
 1362                                 (void)vnode_put(vp);
 1363                         }
 1364                 }
 1365                 kfree(pathbufp, MAXPATHLEN);
 1366                 goto outdrop;
 1367         }
 1368 
 1369         case F_CHKCLEAN:   // used by regression tests to see if all dirty pages got cleaned by fsync()
 1370         case F_FULLFSYNC:  // fsync + flush the journal + DKIOCSYNCHRONIZECACHE
 1371         case F_FREEZE_FS:  // freeze all other fs operations for the fs of this fd
 1372         case F_THAW_FS: {  // thaw all frozen fs operations for the fs of this fd
 1373                 if (fp->f_type != DTYPE_VNODE) {
 1374                         error = EBADF;
 1375                         goto out;
 1376                 }
 1377                 vp = (struct vnode *)fp->f_data;
 1378                 proc_fdunlock(p);
 1379 
 1380                 if ( (error = vnode_getwithref(vp)) == 0 ) {
 1381                         error = VNOP_IOCTL(vp, uap->cmd, (caddr_t)NULL, 0, &context);
 1382 
 1383                         (void)vnode_put(vp);
 1384                 }
 1385                 break;
 1386         }
 1387 
 1388         /*
 1389          * SPI (private) for opening a file starting from a dir fd
 1390          */
 1391         case F_OPENFROM: {
 1392                 struct user_fopenfrom fopen;
 1393                 struct vnode_attr va;
 1394                 struct nameidata nd;
 1395                 int cmode;
 1396 
 1397                 /* Check if this isn't a valid file descriptor */
 1398                 if ((fp->f_type != DTYPE_VNODE) ||
 1399                     (fp->f_flag & FREAD) == 0) {
 1400                         error = EBADF;
 1401                         goto out;
 1402                 }
 1403                 vp = (struct vnode *)fp->f_data;
 1404                 proc_fdunlock(p);
 1405 
 1406                 if (vnode_getwithref(vp)) {
 1407                         error = ENOENT;
 1408                         goto outdrop;
 1409                 }
 1410                 
 1411                 /* Only valid for directories */
 1412                 if (vp->v_type != VDIR) {
 1413                         vnode_put(vp);
 1414                         error = ENOTDIR;
 1415                         goto outdrop;
 1416                 }
 1417 
 1418                 /* Get flags, mode and pathname arguments. */
 1419                 if (IS_64BIT_PROCESS(p)) {
 1420                         error = copyin(argp, &fopen, sizeof(fopen));
 1421                 } else {
 1422                         struct user32_fopenfrom fopen32;
 1423 
 1424                         error = copyin(argp, &fopen32, sizeof(fopen32));
 1425                         fopen.o_flags = fopen32.o_flags;
 1426                         fopen.o_mode = fopen32.o_mode;
 1427                         fopen.o_pathname = CAST_USER_ADDR_T(fopen32.o_pathname);
 1428                 }
 1429                 if (error) {
 1430                         vnode_put(vp);
 1431                         goto outdrop;
 1432                 }
 1433                 AUDIT_ARG(fflags, fopen.o_flags);
 1434                 AUDIT_ARG(mode, fopen.o_mode);
 1435                 VATTR_INIT(&va);
 1436                 /* Mask off all but regular access permissions */
 1437                 cmode = ((fopen.o_mode &~ fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT;
 1438                 VATTR_SET(&va, va_mode, cmode & ACCESSPERMS);
 1439 
 1440                 /* Start the lookup relative to the file descriptor's vnode. */
 1441                 NDINIT(&nd, LOOKUP, OP_OPEN, USEDVP | FOLLOW | AUDITVNPATH1, UIO_USERSPACE,
 1442                        fopen.o_pathname, &context);
 1443                 nd.ni_dvp = vp;
 1444 
 1445                 error = open1(&context, &nd, fopen.o_flags, &va, retval);
 1446 
 1447                 vnode_put(vp);
 1448                 break;
 1449         }
 1450         /*
 1451          * SPI (private) for unlinking a file starting from a dir fd
 1452          */
 1453         case F_UNLINKFROM: {
 1454                 struct nameidata nd;
 1455                 user_addr_t pathname;
 1456 
 1457                 /* Check if this isn't a valid file descriptor */
 1458                 if ((fp->f_type != DTYPE_VNODE) ||
 1459                     (fp->f_flag & FREAD) == 0) {
 1460                         error = EBADF;
 1461                         goto out;
 1462                 }
 1463                 vp = (struct vnode *)fp->f_data;
 1464                 proc_fdunlock(p);
 1465 
 1466                 if (vnode_getwithref(vp)) {
 1467                         error = ENOENT;
 1468                         goto outdrop;
 1469                 }
 1470                 
 1471                 /* Only valid for directories */
 1472                 if (vp->v_type != VDIR) {
 1473                         vnode_put(vp);
 1474                         error = ENOTDIR;
 1475                         goto outdrop;
 1476                 }
 1477 
 1478                 /* Get flags, mode and pathname arguments. */
 1479                 if (IS_64BIT_PROCESS(p)) {
 1480                         pathname = (user_addr_t)argp;
 1481                 } else {
 1482                         pathname = CAST_USER_ADDR_T(argp);
 1483                 }
 1484 
 1485                 /* Start the lookup relative to the file descriptor's vnode. */
 1486                 NDINIT(&nd, DELETE, OP_UNLINK, USEDVP | AUDITVNPATH1, UIO_USERSPACE,
 1487                        pathname, &context);
 1488                 nd.ni_dvp = vp;
 1489 
 1490                 error = unlink1(&context, &nd, 0);
 1491                 
 1492                 vnode_put(vp);
 1493                 break;
 1494 
 1495         }
 1496 
 1497         case F_ADDSIGS:
 1498         case F_ADDFILESIGS:
 1499         {
 1500                 struct user_fsignatures fs;
 1501                 kern_return_t kr;
 1502                 vm_offset_t kernel_blob_addr;
 1503                 vm_size_t kernel_blob_size;
 1504 
 1505                 if (fp->f_type != DTYPE_VNODE) {
 1506                         error = EBADF;
 1507                         goto out;
 1508                 }
 1509                 vp = (struct vnode *)fp->f_data;
 1510                 proc_fdunlock(p);
 1511                 error = vnode_getwithref(vp);
 1512                 if (error)
 1513                         goto outdrop;
 1514 
 1515                 if (IS_64BIT_PROCESS(p)) {
 1516                         error = copyin(argp, &fs, sizeof (fs));
 1517                 } else {
 1518                         struct user32_fsignatures fs32;
 1519 
 1520                         error = copyin(argp, &fs32, sizeof (fs32));
 1521                         fs.fs_file_start = fs32.fs_file_start;
 1522                         fs.fs_blob_start = CAST_USER_ADDR_T(fs32.fs_blob_start);
 1523                         fs.fs_blob_size = fs32.fs_blob_size;
 1524                 }
 1525 
 1526                 if (error) {
 1527                         vnode_put(vp);
 1528                         goto outdrop;
 1529                 }
 1530 
 1531                 if(ubc_cs_blob_get(vp, CPU_TYPE_ANY, fs.fs_file_start))
 1532                 {
 1533                         /*
 1534                         if(cs_debug)
 1535                                 printf("CODE SIGNING: resident blob offered for: %s\n", vp->v_name);
 1536                          */
 1537                         vnode_put(vp);
 1538                         goto outdrop;
 1539                 }
 1540                                    
 1541 #define CS_MAX_BLOB_SIZE (1280ULL * 1024) /* max shared cache file XXX ? */
 1542                 if (fs.fs_blob_size > CS_MAX_BLOB_SIZE) {
 1543                         error = E2BIG;
 1544                         vnode_put(vp);
 1545                         goto outdrop;
 1546                 }
 1547 
 1548                 kernel_blob_size = CAST_DOWN(vm_size_t, fs.fs_blob_size);
 1549                 kr = ubc_cs_blob_allocate(&kernel_blob_addr, &kernel_blob_size);
 1550                 if (kr != KERN_SUCCESS) {
 1551                         error = ENOMEM;
 1552                         vnode_put(vp);
 1553                         goto outdrop;
 1554                 }
 1555 
 1556                 if(uap->cmd == F_ADDSIGS) {
 1557                         error = copyin(fs.fs_blob_start,
 1558                                        (void *) kernel_blob_addr,
 1559                                        kernel_blob_size);
 1560                 } else /* F_ADDFILESIGS */ {
 1561                         error = vn_rdwr(UIO_READ,
 1562                                         vp,
 1563                                         (caddr_t) kernel_blob_addr,
 1564                                         kernel_blob_size,
 1565                                          fs.fs_file_start + fs.fs_blob_start,
 1566                                         UIO_SYSSPACE,
 1567                                         0,
 1568                                         kauth_cred_get(),
 1569                                         0,
 1570                                         p);
 1571                 }
 1572                 
 1573                 if (error) {
 1574                         ubc_cs_blob_deallocate(kernel_blob_addr,
 1575                                                kernel_blob_size);
 1576                         vnode_put(vp);
 1577                         goto outdrop;
 1578                 }
 1579 
 1580                 error = ubc_cs_blob_add(
 1581                         vp,
 1582                         CPU_TYPE_ANY,   /* not for a specific architecture */
 1583                         fs.fs_file_start,
 1584                         kernel_blob_addr,
 1585                         kernel_blob_size);
 1586                 if (error) {
 1587                         ubc_cs_blob_deallocate(kernel_blob_addr,
 1588                                                kernel_blob_size);
 1589                 } else {
 1590                         /* ubc_blob_add() has consumed "kernel_blob_addr" */
 1591 #if CHECK_CS_VALIDATION_BITMAP
 1592                         ubc_cs_validation_bitmap_allocate( vp );
 1593 #endif
 1594                 }
 1595 
 1596                 (void) vnode_put(vp);
 1597                 break;
 1598         }
 1599 
 1600         case F_MARKDEPENDENCY: {
 1601                 struct vnode_attr va;
 1602                 vfs_context_t ctx = vfs_context_current();
 1603                 kauth_cred_t cred;
 1604 
 1605                 if ((current_proc()->p_flag & P_DEPENDENCY_CAPABLE) == 0) {
 1606                     error = EPERM;
 1607                     goto out;
 1608                 }
 1609                 
 1610                 if (fp->f_type != DTYPE_VNODE) {
 1611                         error = EBADF;
 1612                         goto out;
 1613                 }
 1614 
 1615                 vp = (struct vnode *)fp->f_data;
 1616                 proc_fdunlock(p);
 1617 
 1618                 if (vnode_getwithref(vp)) {
 1619                         error = ENOENT;
 1620                         goto outdrop;
 1621                 }
 1622 
 1623                 if (!vnode_isvroot(vp)) {
 1624                     error = EINVAL;
 1625                     vnode_put(vp);
 1626                     goto outdrop;
 1627                 }
 1628 
 1629                 // get the owner of the root dir
 1630                 VATTR_INIT(&va);
 1631                 VATTR_WANTED(&va, va_uid);
 1632                 if (vnode_getattr(vp, &va, ctx) != 0) {
 1633                     error = EINVAL;
 1634                     vnode_put(vp);
 1635                     goto outdrop;
 1636                 }
 1637 
 1638                 // and last, check that the caller is the super user or
 1639                 // the owner of the mount point
 1640                 cred = vfs_context_ucred(ctx);
 1641                 if (!is_suser() && va.va_uid != kauth_cred_getuid(cred)) {
 1642                         error = EACCES;
 1643                         vnode_put(vp);
 1644                         goto outdrop;
 1645                 }
 1646 
 1647                 // if all those checks pass then we can mark the dependency
 1648                 vfs_markdependency(vp->v_mount);
 1649                 error = 0;
 1650                 
 1651                 vnode_put(vp);
 1652                 
 1653                 break;
 1654         }
 1655                         
 1656 #if CONFIG_PROTECT
 1657         case F_GETPROTECTIONCLASS: {
 1658                 int class = 0;
 1659                 
 1660                 if (fp->f_type != DTYPE_VNODE) {
 1661                         error = EBADF;
 1662                         goto out;
 1663                 }
 1664                 vp = (struct vnode *)fp->f_data;
 1665 
 1666                 proc_fdunlock(p);
 1667 
 1668                 if (vnode_getwithref(vp)) {
 1669                         error = ENOENT;
 1670                         goto outdrop;
 1671                 }
 1672         
 1673                 error = cp_vnode_getclass (vp, &class);
 1674                 if (error == 0) {
 1675                         *retval = class;
 1676                 }
 1677 
 1678                 vnode_put(vp);
 1679                 break;
 1680         }
 1681         
 1682         case F_SETPROTECTIONCLASS: {
 1683                 /* tmp must be a valid PROTECTION_CLASS_* */
 1684                 tmp = CAST_DOWN_EXPLICIT(uint32_t, uap->arg);
 1685                 
 1686                 if (fp->f_type != DTYPE_VNODE) {
 1687                         error = EBADF;
 1688                         goto out;
 1689                 }
 1690                 vp = (struct vnode *)fp->f_data;
 1691 
 1692                 proc_fdunlock(p);
 1693         
 1694                 if (vnode_getwithref(vp)) {
 1695                         error = ENOENT;
 1696                         goto outdrop;
 1697                 }       
 1698                 
 1699                 /* Only go forward if you have write access */
 1700                 vfs_context_t ctx = vfs_context_current();
 1701                 if(vnode_authorize(vp, NULLVP, (KAUTH_VNODE_ACCESS | KAUTH_VNODE_WRITE_DATA), ctx) != 0) {
 1702                         vnode_put(vp);
 1703                         error = EBADF;
 1704                         goto outdrop;
 1705                 }
 1706                 error = cp_vnode_setclass (vp, tmp);
 1707                 vnode_put(vp);
 1708                 break;
 1709         }       
 1710 
 1711         case F_TRANSCODEKEY: {
 1712 
 1713                 if (fp->f_type != DTYPE_VNODE) {
 1714                         error = EBADF;
 1715                         goto out;
 1716                 }
 1717                 
 1718                 vp = (struct vnode *)fp->f_data;
 1719                 proc_fdunlock(p);
 1720 
 1721                 if (vnode_getwithref(vp)) {
 1722                         error = ENOENT;
 1723                         goto outdrop;
 1724                 }       
 1725                 
 1726                 error = cp_vnode_transcode (vp);
 1727                 vnode_put(vp);
 1728                 break;
 1729         }       
 1730 
 1731         case F_GETPROTECTIONLEVEL:  {
 1732                 uint32_t cp_version = 0;
 1733 
 1734                 if (fp->f_type != DTYPE_VNODE) {
 1735                         error = EBADF; 
 1736                         goto out;
 1737                 }
 1738 
 1739                 vp = (struct vnode*) fp->f_data;
 1740                 proc_fdunlock (p);
 1741 
 1742                 if (vnode_getwithref(vp)) {
 1743                         error = ENOENT;
 1744                         goto outdrop;
 1745                 }
 1746 
 1747                 /*
 1748                  * if cp_get_major_vers fails, error will be set to proper errno 
 1749                  * and cp_version will still be 0.
 1750                  */
 1751 
 1752                 error = cp_get_root_major_vers (vp, &cp_version);
 1753                 *retval = cp_version;
 1754 
 1755                 vnode_put (vp);
 1756                 break;
 1757         }
 1758         
 1759 #endif /* CONFIG_PROTECT */
 1760 
 1761         case F_MOVEDATAEXTENTS: {
 1762                 struct fileproc *fp2 = NULL;
 1763                 struct vnode *src_vp = NULLVP;
 1764                 struct vnode *dst_vp = NULLVP;
 1765                 /* We need to grab the 2nd FD out of the argments before moving on. */
 1766                 int fd2 = CAST_DOWN_EXPLICIT(int32_t, uap->arg);
 1767                 
 1768                 if (fp->f_type != DTYPE_VNODE) {
 1769                         error = EBADF;
 1770                         goto out;
 1771                 }
 1772 
 1773                 /* For now, special case HFS+ only, since this is SPI. */
 1774                 src_vp = (struct vnode *)fp->f_data;
 1775                 if (src_vp->v_tag != VT_HFS) {
 1776                         error = EINVAL;
 1777                         goto out;
 1778                 }
 1779 
 1780                 /*
 1781                  * Get the references before we start acquiring iocounts on the vnodes, 
 1782                  * while we still hold the proc fd lock
 1783                  */
 1784                 if ( (error = fp_lookup(p, fd2, &fp2, 1)) ) {
 1785                         error = EBADF;
 1786                         goto out;
 1787                 }
 1788                 if (fp2->f_type != DTYPE_VNODE) {
 1789                         fp_drop(p, fd2, fp2, 1);
 1790                         error = EBADF;
 1791                         goto out;
 1792                 }
 1793                 dst_vp = (struct vnode *)fp2->f_data;
 1794                 if (dst_vp->v_tag != VT_HFS) {
 1795                         fp_drop(p, fd2, fp2, 1);
 1796                         error = EINVAL;
 1797                         goto out;
 1798                 }
 1799 
 1800 #if CONFIG_MACF
 1801                 /* Re-do MAC checks against the new FD, pass in a fake argument */
 1802                 error = mac_file_check_fcntl(proc_ucred(p), fp2->f_fglob, uap->cmd, 0);
 1803                 if (error) {
 1804                         fp_drop(p, fd2, fp2, 1);
 1805                         goto out;
 1806                 }
 1807 #endif
 1808                 /* Audit the 2nd FD */
 1809                 AUDIT_ARG(fd, fd2);
 1810 
 1811                 proc_fdunlock(p);
 1812 
 1813                 if (vnode_getwithref(src_vp)) {
 1814                         fp_drop(p, fd2, fp2, 0);
 1815                         error = ENOENT;
 1816                         goto outdrop;
 1817                 }       
 1818                 if (vnode_getwithref(dst_vp)) {
 1819                         vnode_put (src_vp);
 1820                         fp_drop(p, fd2, fp2, 0);
 1821                         error = ENOENT;
 1822                         goto outdrop;
 1823                 }       
 1824                 
 1825                 /* 
 1826                  * Basic asserts; validate they are not the same and that
 1827                  * both live on the same filesystem.
 1828                  */
 1829                 if (dst_vp == src_vp) {
 1830                         vnode_put (src_vp);
 1831                         vnode_put (dst_vp);
 1832                         fp_drop (p, fd2, fp2, 0);
 1833                         error = EINVAL;
 1834                         goto outdrop;
 1835                 }       
 1836 
 1837                 if (dst_vp->v_mount != src_vp->v_mount) {
 1838                         vnode_put (src_vp);
 1839                         vnode_put (dst_vp);
 1840                         fp_drop (p, fd2, fp2, 0);
 1841                         error = EXDEV;
 1842                         goto outdrop;
 1843                 }
 1844 
 1845                 /* Now we have a legit pair of FDs.  Go to work */
 1846 
 1847                 /* Now check for write access to the target files */
 1848                 if(vnode_authorize(src_vp, NULLVP, 
 1849                                                    (KAUTH_VNODE_ACCESS | KAUTH_VNODE_WRITE_DATA), &context) != 0) {
 1850                         vnode_put(src_vp);
 1851                         vnode_put(dst_vp);
 1852                         fp_drop(p, fd2, fp2, 0);
 1853                         error = EBADF;
 1854                         goto outdrop;
 1855                 }
 1856                 
 1857                 if(vnode_authorize(dst_vp, NULLVP, 
 1858                                                    (KAUTH_VNODE_ACCESS | KAUTH_VNODE_WRITE_DATA), &context) != 0) {
 1859                         vnode_put(src_vp);
 1860                         vnode_put(dst_vp);
 1861                         fp_drop(p, fd2, fp2, 0);
 1862                         error = EBADF;
 1863                         goto outdrop;
 1864                 }
 1865                         
 1866                 /* Verify that both vps point to files and not directories */
 1867                 if ( !vnode_isreg(src_vp) || !vnode_isreg(dst_vp)) {
 1868                         error = EINVAL;
 1869                         vnode_put (src_vp);
 1870                         vnode_put (dst_vp);
 1871                         fp_drop (p, fd2, fp2, 0);
 1872                         goto outdrop;
 1873                 }
 1874 
 1875                 /* 
 1876                  * The exchangedata syscall handler passes in 0 for the flags to VNOP_EXCHANGE.
 1877                  * We'll pass in our special bit indicating that the new behavior is expected
 1878                  */
 1879                 
 1880                 error = VNOP_EXCHANGE(src_vp, dst_vp, FSOPT_EXCHANGE_DATA_ONLY, &context);
 1881                 
 1882                 vnode_put (src_vp);
 1883                 vnode_put (dst_vp);
 1884                 fp_drop(p, fd2, fp2, 0);
 1885                 break;
 1886         }
 1887                         
 1888                         
 1889         /*
 1890          * SPI (private) for indicating to a filesystem that subsequent writes to
 1891          * the open FD will represent static content.
 1892          */
 1893         case F_SETSTATICCONTENT: {
 1894                 caddr_t ioctl_arg = NULL;
 1895 
 1896                 if (uap->arg) {
 1897                         ioctl_arg = (caddr_t) 1;
 1898                 }
 1899 
 1900                 if (fp->f_type != DTYPE_VNODE) {
 1901                         error = EBADF;
 1902                         goto out;
 1903                 }
 1904                 vp = (struct vnode *)fp->f_data;
 1905                 proc_fdunlock(p);
 1906 
 1907                 error = vnode_getwithref(vp);
 1908                 if (error) {
 1909                         error = ENOENT;
 1910                         goto outdrop;
 1911                 }
 1912 
 1913                 /* Only go forward if you have write access */
 1914                 vfs_context_t ctx = vfs_context_current();
 1915                 if(vnode_authorize(vp, NULLVP, (KAUTH_VNODE_ACCESS | KAUTH_VNODE_WRITE_DATA), ctx) != 0) {
 1916                         vnode_put(vp);
 1917                         error = EBADF;
 1918                         goto outdrop;
 1919                 }
 1920 
 1921                 error = VNOP_IOCTL(vp, uap->cmd, ioctl_arg, 0, &context);
 1922                 (void)vnode_put(vp);
 1923                 
 1924                 break;
 1925         }
 1926         
 1927         /* 
 1928          * Set the vnode pointed to by 'fd'
 1929          * and tag it as the (potentially future) backing store
 1930          * for another filesystem
 1931          */
 1932         case F_SETBACKINGSTORE: {
 1933                 if (fp->f_type != DTYPE_VNODE) {
 1934                         error = EBADF;
 1935                         goto out;
 1936                 }
 1937                 
 1938                 vp = (struct vnode *)fp->f_data;
 1939 
 1940                 if (vp->v_tag != VT_HFS) {
 1941                         error = EINVAL;
 1942                         goto out;
 1943                 }
 1944                 proc_fdunlock(p);
 1945 
 1946                 if (vnode_getwithref(vp)) {
 1947                         error = ENOENT;
 1948                         goto outdrop;
 1949                 }
 1950                 
 1951                 /* only proceed if you have write access */
 1952                 vfs_context_t ctx = vfs_context_current();
 1953                 if(vnode_authorize(vp, NULLVP, (KAUTH_VNODE_ACCESS | KAUTH_VNODE_WRITE_DATA), ctx) != 0) {
 1954                         vnode_put(vp);
 1955                         error = EBADF;
 1956                         goto outdrop;
 1957                 }
 1958 
 1959                 
 1960                 /* If arg != 0, set, otherwise unset */
 1961                 if (uap->arg) {
 1962                         error = VNOP_IOCTL (vp, uap->cmd, (caddr_t)1, 0, &context);
 1963                 }
 1964                 else {
 1965                         error = VNOP_IOCTL (vp, uap->cmd, (caddr_t)NULL, 0, &context);
 1966                 }
 1967                 
 1968                 vnode_put(vp);
 1969                 break;
 1970         }
 1971 
 1972         /* 
 1973          * like F_GETPATH, but special semantics for
 1974          * the mobile time machine handler.
 1975          */
 1976         case F_GETPATH_MTMINFO: {
 1977                 char *pathbufp;
 1978                 int pathlen;
 1979 
 1980                 if (fp->f_type != DTYPE_VNODE) {
 1981                         error = EBADF;
 1982                         goto out;
 1983                 }
 1984                 vp = (struct vnode *)fp->f_data;
 1985                 proc_fdunlock(p);
 1986 
 1987                 pathlen = MAXPATHLEN;
 1988                 MALLOC(pathbufp, char *, pathlen, M_TEMP, M_WAITOK);
 1989                 if (pathbufp == NULL) {
 1990                         error = ENOMEM;
 1991                         goto outdrop;
 1992                 }
 1993                 if ( (error = vnode_getwithref(vp)) == 0 ) {
 1994                         int backingstore = 0;
 1995                         
 1996                         /* Check for error from vn_getpath before moving on */
 1997                         if ((error = vn_getpath(vp, pathbufp, &pathlen)) == 0) {
 1998                                 if (vp->v_tag == VT_HFS) {
 1999                                         error = VNOP_IOCTL (vp, uap->cmd, (caddr_t) &backingstore, 0, &context);
 2000                                 }
 2001                                 (void)vnode_put(vp);
 2002 
 2003                                 if (error == 0) {
 2004                                         error = copyout((caddr_t)pathbufp, argp, pathlen);
 2005                                 }
 2006                                 if (error == 0) {
 2007                                         /* 
 2008                                          * If the copyout was successful, now check to ensure
 2009                                          * that this vnode is not a BACKINGSTORE vnode.  mtmd
 2010                                          * wants the path regardless.
 2011                                          */
 2012                                         if (backingstore) {
 2013                                                 error = EBUSY;
 2014                                         }
 2015                                 }
 2016                         } else
 2017                                 (void)vnode_put(vp);
 2018                 }
 2019                 FREE(pathbufp, M_TEMP);
 2020                 goto outdrop;
 2021         }
 2022 
 2023         default:
 2024                 /*
 2025                  * This is an fcntl() that we d not recognize at this level;
 2026                  * if this is a vnode, we send it down into the VNOP_IOCTL
 2027                  * for this vnode; this can include special devices, and will
 2028                  * effectively overload fcntl() to send ioctl()'s.
 2029                  */
 2030                 if((uap->cmd & IOC_VOID) && (uap->cmd & IOC_INOUT)){
 2031                         error = EINVAL;
 2032                         goto out;
 2033                 }
 2034                 
 2035                 if (fp->f_type != DTYPE_VNODE) {
 2036                         error = EBADF;
 2037                         goto out;
 2038                 }
 2039                 vp = (struct vnode *)fp->f_data;
 2040                 proc_fdunlock(p);
 2041 
 2042                 if ( (error = vnode_getwithref(vp)) == 0 ) {
 2043 #define STK_PARAMS 128
 2044                         char stkbuf[STK_PARAMS];
 2045                         unsigned int size;
 2046                         caddr_t data, memp;
 2047                         /*
 2048                          * For this to work properly, we have to copy in the
 2049                          * ioctl() cmd argument if there is one; we must also
 2050                          * check that a command parameter, if present, does
 2051                          * not exceed the maximum command length dictated by
 2052                          * the number of bits we have available in the command
 2053                          * to represent a structure length.  Finally, we have
 2054                          * to copy the results back out, if it is that type of
 2055                          * ioctl().
 2056                          */
 2057                         size = IOCPARM_LEN(uap->cmd);
 2058                         if (size > IOCPARM_MAX) {
 2059                                 (void)vnode_put(vp);
 2060                                 error = EINVAL;
 2061                                 break;
 2062                         }
 2063 
 2064                         memp = NULL;
 2065                         if (size > sizeof (stkbuf)) {
 2066                                 if ((memp = (caddr_t)kalloc(size)) == 0) {
 2067                                         (void)vnode_put(vp);
 2068                                         error = ENOMEM;
 2069                                         goto outdrop;
 2070                                 }
 2071                                 data = memp;
 2072                         } else {
 2073                                 data = &stkbuf[0];
 2074                         }
 2075                         
 2076                         if (uap->cmd & IOC_IN) {
 2077                                 if (size) {
 2078                                         /* structure */
 2079                                         error = copyin(argp, data, size);
 2080                                         if (error) {
 2081                                                 (void)vnode_put(vp);
 2082                                                 if (memp)
 2083                                                         kfree(memp, size);
 2084                                                 goto outdrop;
 2085                                         }
 2086                                 } else {
 2087                                         /* int */
 2088                                         if (is64bit) {
 2089                                                 *(user_addr_t *)data = argp;
 2090                                         } else {
 2091                                                 *(uint32_t *)data = (uint32_t)argp;
 2092                                         }
 2093                                 };
 2094                         } else if ((uap->cmd & IOC_OUT) && size) {
 2095                                 /*
 2096                                  * Zero the buffer so the user always
 2097                                  * gets back something deterministic.
 2098                                  */
 2099                                 bzero(data, size);
 2100                         } else if (uap->cmd & IOC_VOID) {
 2101                                 if (is64bit) {
 2102                                     *(user_addr_t *)data = argp;
 2103                                 } else {
 2104                                     *(uint32_t *)data = (uint32_t)argp;
 2105                                 }
 2106                         }
 2107 
 2108                         error = VNOP_IOCTL(vp, uap->cmd, CAST_DOWN(caddr_t, data), 0, &context);
 2109 
 2110                         (void)vnode_put(vp);
 2111 
 2112                         /* Copy any output data to user */
 2113                         if (error == 0 && (uap->cmd & IOC_OUT) && size) 
 2114                                 error = copyout(data, argp, size);
 2115                         if (memp)
 2116                                 kfree(memp, size);
 2117                 }
 2118                 break;
 2119         }
 2120 
 2121 outdrop:
 2122         AUDIT_ARG(vnpath_withref, vp, ARG_VNODE1);
 2123         fp_drop(p, fd, fp, 0);
 2124         return(error);
 2125 out:
 2126         fp_drop(p, fd, fp, 1);
 2127         proc_fdunlock(p);
 2128         return(error);
 2129 }
 2130 
 2131 
 2132 /*
 2133  * finishdup
 2134  *
 2135  * Description: Common code for dup, dup2, and fcntl(F_DUPFD).
 2136  *
 2137  * Parameters:  p                               Process performing the dup
 2138  *              old                             The fd to dup
 2139  *              new                             The fd to dup it to
 2140  *              fd_flags                        Flags to augment the new fd
 2141  *              retval                          Pointer to the call return area
 2142  *
 2143  * Returns:     0                               Success
 2144  *              EBADF
 2145  *              ENOMEM
 2146  *
 2147  * Implicit returns:
 2148  *              *retval (modified)              The new descriptor
 2149  *
 2150  * Locks:       Assumes proc_fdlock for process pointing to fdp is held by
 2151  *              the caller
 2152  *
 2153  * Notes:       This function may drop and reacquire this lock; it is unsafe
 2154  *              for a caller to assume that other state protected by the lock
 2155  *              has not been subsequently changed out from under it.
 2156  */
 2157 int
 2158 finishdup(proc_t p,
 2159     struct filedesc *fdp, int old, int new, int fd_flags, int32_t *retval)
 2160 {
 2161         struct fileproc *nfp;
 2162         struct fileproc *ofp;
 2163 #if CONFIG_MACF
 2164         int error;
 2165 #endif
 2166 
 2167 #if DIAGNOSTIC
 2168         proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
 2169 #endif
 2170         if ((ofp = fdp->fd_ofiles[old]) == NULL ||
 2171             (fdp->fd_ofileflags[old] & UF_RESERVED)) {
 2172                 fdrelse(p, new);
 2173                 return (EBADF);
 2174         }
 2175         fg_ref(ofp);
 2176 
 2177 #if CONFIG_MACF
 2178         error = mac_file_check_dup(proc_ucred(p), ofp->f_fglob, new);
 2179         if (error) {
 2180                 fg_drop(ofp);
 2181                 fdrelse(p, new);
 2182                 return (error);
 2183         }
 2184 #endif
 2185 
 2186         proc_fdunlock(p);
 2187 
 2188         MALLOC_ZONE(nfp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
 2189         /* Failure check follows proc_fdlock() due to handling requirements */
 2190 
 2191         proc_fdlock(p);
 2192 
 2193         if (nfp == NULL) {
 2194                 fg_drop(ofp);
 2195                 fdrelse(p, new);
 2196                 return (ENOMEM);
 2197         }
 2198 
 2199         bzero(nfp, sizeof(struct fileproc));
 2200 
 2201         nfp->f_flags = 0;
 2202         nfp->f_fglob = ofp->f_fglob;
 2203         nfp->f_iocount = 0;
 2204 
 2205 #if DIAGNOSTIC
 2206         if (fdp->fd_ofiles[new] != 0)
 2207                 panic("finishdup: overwriting fd_ofiles with new %d", new);
 2208         if ((fdp->fd_ofileflags[new] & UF_RESERVED) == 0)
 2209                 panic("finishdup: unreserved fileflags with new %d", new);
 2210 #endif
 2211 
 2212         if (new > fdp->fd_lastfile)
 2213                 fdp->fd_lastfile = new;
 2214         *fdflags(p, new) |= fd_flags;
 2215         procfdtbl_releasefd(p, new, nfp);
 2216         *retval = new;
 2217         return (0);
 2218 }
 2219 
 2220 
 2221 /*
 2222  * close
 2223  *
 2224  * Description: The implementation of the close(2) system call
 2225  *
 2226  * Parameters:  p                       Process in whose per process file table
 2227  *                                      the close is to occur
 2228  *              uap->fd                 fd to be closed
 2229  *              retval                  <unused>
 2230  *
 2231  * Returns:     0                       Success
 2232  *      fp_lookup:EBADF                 Bad file descriptor
 2233  *      close_internal:EBADF
 2234  *      close_internal:???              Anything returnable by a per-fileops
 2235  *                                      close function
 2236  */
 2237 int
 2238 close(proc_t p, struct close_args *uap, int32_t *retval)
 2239 {
 2240         __pthread_testcancel(1);
 2241         return(close_nocancel(p, (struct close_nocancel_args *)uap, retval));
 2242 }
 2243 
 2244 
 2245 int
 2246 close_nocancel(proc_t p, struct close_nocancel_args *uap, __unused int32_t *retval)
 2247 {
 2248         struct fileproc *fp;
 2249         int fd = uap->fd;
 2250         int error =0;
 2251 
 2252         AUDIT_SYSCLOSE(p, fd);
 2253 
 2254         proc_fdlock(p);
 2255 
 2256         if ( (error = fp_lookup(p,fd,&fp, 1)) ) {
 2257                 proc_fdunlock(p);
 2258                 return(error);
 2259         }
 2260 
 2261         error = close_internal_locked(p, fd, fp, 0);
 2262 
 2263         proc_fdunlock(p);
 2264 
 2265         return(error);
 2266 }
 2267 
 2268 
 2269 /*
 2270  * close_internal_locked
 2271  *
 2272  * Close a file descriptor.
 2273  *
 2274  * Parameters:  p                       Process in whose per process file table
 2275  *                                      the close is to occur
 2276  *              fd                      fd to be closed
 2277  *              fp                      fileproc associated with the fd
 2278  *
 2279  * Returns:     0                       Success
 2280  *              EBADF                   fd already in close wait state
 2281  *      closef_locked:???               Anything returnable by a per-fileops
 2282  *                                      close function
 2283  *
 2284  * Locks:       Assumes proc_fdlock for process is held by the caller and returns
 2285  *              with lock held
 2286  *
 2287  * Notes:       This function may drop and reacquire this lock; it is unsafe
 2288  *              for a caller to assume that other state protected by the lock
 2289  *              has not been subsequently changes out from under it, if the
 2290  *              caller made the call with the lock held.
 2291  */
 2292 static int
 2293 close_internal_locked(proc_t p, int fd, struct fileproc *fp, int flags)
 2294 {
 2295         struct filedesc *fdp = p->p_fd;
 2296         int error =0;
 2297         int resvfd = flags & FD_DUP2RESV;
 2298 
 2299 
 2300 #if DIAGNOSTIC
 2301         proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
 2302 #endif
 2303 
 2304         /* Keep people from using the filedesc while we are closing it */
 2305         procfdtbl_markclosefd(p, fd);
 2306 
 2307 
 2308         if ((fp->f_flags & FP_CLOSING) == FP_CLOSING) {
 2309                 panic("close_internal_locked: being called on already closing fd");
 2310         }
 2311 
 2312 
 2313 #if DIAGNOSTIC
 2314         if ((fdp->fd_ofileflags[fd] & UF_RESERVED) == 0)
 2315                 panic("close_internal: unreserved fileflags with fd %d", fd);
 2316 #endif
 2317 
 2318         fp->f_flags |= FP_CLOSING;
 2319 
 2320         if ( (fp->f_flags & FP_AIOISSUED) || kauth_authorize_fileop_has_listeners() ) {
 2321 
 2322                 proc_fdunlock(p);
 2323 
 2324                 if ( (fp->f_type == DTYPE_VNODE) && kauth_authorize_fileop_has_listeners() ) {
 2325                         /*
 2326                          * call out to allow 3rd party notification of close. 
 2327                          * Ignore result of kauth_authorize_fileop call.
 2328                          */
 2329                         if (vnode_getwithref((vnode_t)fp->f_data) == 0) {
 2330                                 u_int   fileop_flags = 0;
 2331                                 if ((fp->f_flags & FP_WRITTEN) != 0)
 2332                                         fileop_flags |= KAUTH_FILEOP_CLOSE_MODIFIED;
 2333                                 kauth_authorize_fileop(fp->f_fglob->fg_cred, KAUTH_FILEOP_CLOSE, 
 2334                                                        (uintptr_t)fp->f_data, (uintptr_t)fileop_flags);
 2335                                 vnode_put((vnode_t)fp->f_data);
 2336                         }
 2337                 }
 2338                 if (fp->f_flags & FP_AIOISSUED)
 2339                         /*
 2340                          * cancel all async IO requests that can be cancelled.
 2341                          */
 2342                         _aio_close( p, fd );
 2343 
 2344                 proc_fdlock(p);
 2345         }
 2346 
 2347         if (fd < fdp->fd_knlistsize)
 2348                 knote_fdclose(p, fd);
 2349 
 2350         if (fp->f_flags & FP_WAITEVENT) 
 2351                 (void)waitevent_close(p, fp);
 2352 
 2353         if ((fp->f_flags & FP_INCHRREAD) == 0)
 2354                 fileproc_drain(p, fp);
 2355 
 2356         if (resvfd == 0)
 2357                 _fdrelse(p, fd);
 2358 
 2359         error = closef_locked(fp, fp->f_fglob, p);
 2360         if ((fp->f_flags & FP_WAITCLOSE) == FP_WAITCLOSE)
 2361                 wakeup(&fp->f_flags);
 2362         fp->f_flags &= ~(FP_WAITCLOSE | FP_CLOSING);
 2363 
 2364         proc_fdunlock(p);
 2365 
 2366         FREE_ZONE(fp, sizeof(*fp), M_FILEPROC); 
 2367 
 2368         proc_fdlock(p);
 2369 
 2370 #if DIAGNOSTIC
 2371         if (resvfd != 0) {
 2372                 if ((fdp->fd_ofileflags[fd] & UF_RESERVED) == 0)
 2373                         panic("close with reserved fd returns with freed fd:%d: proc: %p", fd, p);
 2374         }
 2375 #endif
 2376 
 2377         return(error);
 2378 }
 2379 
 2380 
 2381 /*
 2382  * fstat1
 2383  *
 2384  * Description: Return status information about a file descriptor.
 2385  *
 2386  * Parameters:  p                               The process doing the fstat
 2387  *              fd                              The fd to stat
 2388  *              ub                              The user stat buffer
 2389  *              xsecurity                       The user extended security
 2390  *                                              buffer, or 0 if none
 2391  *              xsecurity_size                  The size of xsecurity, or 0
 2392  *                                              if no xsecurity
 2393  *              isstat64                        Flag to indicate 64 bit version
 2394  *                                              for inode size, etc.
 2395  *
 2396  * Returns:     0                               Success
 2397  *              EBADF
 2398  *              EFAULT
 2399  *      fp_lookup:EBADF                         Bad file descriptor
 2400  *      vnode_getwithref:???
 2401  *      copyout:EFAULT
 2402  *      vnode_getwithref:???
 2403  *      vn_stat:???
 2404  *      soo_stat:???
 2405  *      pipe_stat:???
 2406  *      pshm_stat:???
 2407  *      kqueue_stat:???
 2408  *
 2409  * Notes:       Internal implementation for all other fstat() related
 2410  *              functions
 2411  *
 2412  *              XXX switch on node type is bogus; need a stat in struct
 2413  *              XXX fileops instead.
 2414  */
 2415 static int
 2416 fstat1(proc_t p, int fd, user_addr_t ub, user_addr_t xsecurity, user_addr_t xsecurity_size, int isstat64)
 2417 {
 2418         struct fileproc *fp;
 2419         union {
 2420                 struct stat sb;
 2421                 struct stat64 sb64;
 2422         } source;
 2423         union {
 2424                 struct user64_stat user64_sb;
 2425                 struct user32_stat user32_sb;
 2426                 struct user64_stat64 user64_sb64;
 2427                 struct user32_stat64 user32_sb64;
 2428         } dest;
 2429         int error, my_size;
 2430         int funnel_state;
 2431         file_type_t type;
 2432         caddr_t data;
 2433         kauth_filesec_t fsec;
 2434         user_size_t xsecurity_bufsize;
 2435         vfs_context_t ctx = vfs_context_current();
 2436         void * sbptr;
 2437 
 2438 
 2439         AUDIT_ARG(fd, fd);
 2440 
 2441         if ((error = fp_lookup(p, fd, &fp, 0)) != 0) {
 2442                 return(error);
 2443         }
 2444         type = fp->f_type;
 2445         data = fp->f_data;
 2446         fsec = KAUTH_FILESEC_NONE;
 2447 
 2448         sbptr = (void *)&source;
 2449 
 2450         switch (type) {
 2451 
 2452         case DTYPE_VNODE:
 2453                 if ((error = vnode_getwithref((vnode_t)data)) == 0) {
 2454                         /*
 2455                          * If the caller has the file open, and is not
 2456                          * requesting extended security information, we are
 2457                          * going to let them get the basic stat information.
 2458                          */
 2459                         if (xsecurity == USER_ADDR_NULL) {
 2460                                 error = vn_stat_noauth((vnode_t)data, sbptr, NULL, isstat64, ctx);
 2461                         } else {
 2462                                 error = vn_stat((vnode_t)data, sbptr, &fsec, isstat64, ctx);
 2463                         }
 2464 
 2465                         AUDIT_ARG(vnpath, (struct vnode *)data, ARG_VNODE1);
 2466                         (void)vnode_put((vnode_t)data);
 2467                 }
 2468                 break;
 2469 
 2470 #if SOCKETS
 2471         case DTYPE_SOCKET:
 2472                 error = soo_stat((struct socket *)data, sbptr, isstat64);
 2473                 break;
 2474 #endif /* SOCKETS */
 2475 
 2476         case DTYPE_PIPE:
 2477                 error = pipe_stat((void *)data, sbptr, isstat64);
 2478                 break;
 2479 
 2480         case DTYPE_PSXSHM:
 2481                 error = pshm_stat((void *)data, sbptr, isstat64);
 2482                 break;
 2483 
 2484         case DTYPE_KQUEUE:
 2485                 funnel_state = thread_funnel_set(kernel_flock, TRUE);
 2486                 error = kqueue_stat(fp, sbptr, isstat64, p);
 2487                 thread_funnel_set(kernel_flock, funnel_state);
 2488                 break;
 2489 
 2490         default:
 2491                 error = EBADF;
 2492                 goto out;
 2493         }
 2494         if (error == 0) {
 2495                 caddr_t sbp;
 2496 
 2497                 if (isstat64 != 0) {
 2498                         source.sb64.st_lspare = 0;
 2499                         source.sb64.st_qspare[0] = 0LL;
 2500                         source.sb64.st_qspare[1] = 0LL;
 2501 
 2502                         if (IS_64BIT_PROCESS(current_proc())) {
 2503                                 munge_user64_stat64(&source.sb64, &dest.user64_sb64); 
 2504                                 my_size = sizeof(dest.user64_sb64);
 2505                                 sbp = (caddr_t)&dest.user64_sb64;
 2506                         } else {
 2507                                 munge_user32_stat64(&source.sb64, &dest.user32_sb64); 
 2508                                 my_size = sizeof(dest.user32_sb64);
 2509                                 sbp = (caddr_t)&dest.user32_sb64;
 2510                         }
 2511                 } else {
 2512                         source.sb.st_lspare = 0;
 2513                         source.sb.st_qspare[0] = 0LL;
 2514                         source.sb.st_qspare[1] = 0LL;
 2515                         if (IS_64BIT_PROCESS(current_proc())) {
 2516                                 munge_user64_stat(&source.sb, &dest.user64_sb); 
 2517                                 my_size = sizeof(dest.user64_sb);
 2518                                 sbp = (caddr_t)&dest.user64_sb;
 2519                         } else {
 2520                                 munge_user32_stat(&source.sb, &dest.user32_sb); 
 2521                                 my_size = sizeof(dest.user32_sb);
 2522                                 sbp = (caddr_t)&dest.user32_sb;
 2523                         }
 2524                 }
 2525 
 2526                 error = copyout(sbp, ub, my_size);
 2527         }
 2528 
 2529         /* caller wants extended security information? */
 2530         if (xsecurity != USER_ADDR_NULL) {
 2531 
 2532                 /* did we get any? */
 2533                  if (fsec == KAUTH_FILESEC_NONE) {
 2534                         if (susize(xsecurity_size, 0) != 0) {
 2535                                 error = EFAULT;
 2536                                 goto out;
 2537                         }
 2538                 } else {
 2539                         /* find the user buffer size */
 2540                         xsecurity_bufsize = fusize(xsecurity_size);
 2541 
 2542                         /* copy out the actual data size */
 2543                         if (susize(xsecurity_size, KAUTH_FILESEC_COPYSIZE(fsec)) != 0) {
 2544                                 error = EFAULT;
 2545                                 goto out;
 2546                         }
 2547 
 2548                         /* if the caller supplied enough room, copy out to it */
 2549                         if (xsecurity_bufsize >= KAUTH_FILESEC_COPYSIZE(fsec))
 2550                                 error = copyout(fsec, xsecurity, KAUTH_FILESEC_COPYSIZE(fsec));
 2551                 }
 2552         }
 2553 out:
 2554         fp_drop(p, fd, fp, 0);
 2555         if (fsec != NULL)
 2556                 kauth_filesec_free(fsec);
 2557         return (error);
 2558 }
 2559 
 2560 
 2561 /*
 2562  * fstat_extended
 2563  *
 2564  * Description: Extended version of fstat supporting returning extended
 2565  *              security information
 2566  *
 2567  * Parameters:  p                               The process doing the fstat
 2568  *              uap->fd                         The fd to stat
 2569  *              uap->ub                         The user stat buffer
 2570  *              uap->xsecurity                  The user extended security
 2571  *                                              buffer, or 0 if none
 2572  *              uap->xsecurity_size             The size of xsecurity, or 0
 2573  *
 2574  * Returns:     0                               Success
 2575  *              !0                              Errno (see fstat1)
 2576  */
 2577 int
 2578 fstat_extended(proc_t p, struct fstat_extended_args *uap, __unused int32_t *retval)
 2579 {
 2580         return(fstat1(p, uap->fd, uap->ub, uap->xsecurity, uap->xsecurity_size, 0));
 2581 }
 2582  
 2583 
 2584 /*
 2585  * fstat
 2586  *
 2587  * Description: Get file status for the file associated with fd
 2588  *
 2589  * Parameters:  p                               The process doing the fstat
 2590  *              uap->fd                         The fd to stat
 2591  *              uap->ub                         The user stat buffer
 2592  *
 2593  * Returns:     0                               Success
 2594  *              !0                              Errno (see fstat1)
 2595  */
 2596 int
 2597 fstat(proc_t p, register struct fstat_args *uap, __unused int32_t *retval)
 2598 {
 2599         return(fstat1(p, uap->fd, uap->ub, 0, 0, 0));
 2600 }
 2601 
 2602 
 2603 /*
 2604  * fstat64_extended
 2605  *
 2606  * Description: Extended version of fstat64 supporting returning extended
 2607  *              security information
 2608  *
 2609  * Parameters:  p                               The process doing the fstat
 2610  *              uap->fd                         The fd to stat
 2611  *              uap->ub                         The user stat buffer
 2612  *              uap->xsecurity                  The user extended security
 2613  *                                              buffer, or 0 if none
 2614  *              uap->xsecurity_size             The size of xsecurity, or 0
 2615  *
 2616  * Returns:     0                               Success
 2617  *              !0                              Errno (see fstat1)
 2618  */
 2619 int
 2620 fstat64_extended(proc_t p, struct fstat64_extended_args *uap, __unused int32_t *retval)
 2621 {
 2622         return(fstat1(p, uap->fd, uap->ub, uap->xsecurity, uap->xsecurity_size, 1));
 2623 }
 2624  
 2625 
 2626 /*
 2627  * fstat64
 2628  *
 2629  * Description: Get 64 bit version of the file status for the file associated
 2630  *              with fd
 2631  *
 2632  * Parameters:  p                               The process doing the fstat
 2633  *              uap->fd                         The fd to stat
 2634  *              uap->ub                         The user stat buffer
 2635  *
 2636  * Returns:     0                               Success
 2637  *              !0                              Errno (see fstat1)
 2638  */
 2639 int
 2640 fstat64(proc_t p, register struct fstat64_args *uap, __unused int32_t *retval)
 2641 {
 2642         return(fstat1(p, uap->fd, uap->ub, 0, 0, 1));
 2643 }
 2644 
 2645 
 2646 /*
 2647  * fpathconf
 2648  *
 2649  * Description: Return pathconf information about a file descriptor.
 2650  *
 2651  * Parameters:  p                               Process making the request
 2652  *              uap->fd                         fd to get information about
 2653  *              uap->name                       Name of information desired
 2654  *              retval                          Pointer to the call return area
 2655  *
 2656  * Returns:     0                               Success
 2657  *              EINVAL
 2658  *      fp_lookup:EBADF                         Bad file descriptor
 2659  *      vnode_getwithref:???
 2660  *      vn_pathconf:???
 2661  *
 2662  * Implicit returns:
 2663  *              *retval (modified)              Returned information (numeric)
 2664  */
 2665 int
 2666 fpathconf(proc_t p, struct fpathconf_args *uap, int32_t *retval)
 2667 {
 2668         int fd = uap->fd;
 2669         struct fileproc *fp;
 2670         struct vnode *vp;
 2671         int error = 0;
 2672         file_type_t type;
 2673         caddr_t data;
 2674 
 2675 
 2676         AUDIT_ARG(fd, uap->fd);
 2677         if ( (error = fp_lookup(p, fd, &fp, 0)) )
 2678                 return(error);
 2679         type = fp->f_type;
 2680         data = fp->f_data;
 2681 
 2682         switch (type) {
 2683 
 2684         case DTYPE_SOCKET:
 2685                 if (uap->name != _PC_PIPE_BUF) {
 2686                         error = EINVAL;
 2687                         goto out;
 2688                 }
 2689                 *retval = PIPE_BUF;
 2690                 error = 0;
 2691                 goto out;
 2692 
 2693         case DTYPE_PIPE:
 2694                 if (uap->name != _PC_PIPE_BUF) {
 2695                         error = EINVAL;
 2696                         goto out;
 2697                 }
 2698                 *retval = PIPE_BUF;
 2699                 error = 0;
 2700                 goto out;
 2701 
 2702         case DTYPE_VNODE:
 2703                 vp = (struct vnode *)data;
 2704 
 2705                 if ( (error = vnode_getwithref(vp)) == 0) {
 2706                         AUDIT_ARG(vnpath, vp, ARG_VNODE1);
 2707 
 2708                         error = vn_pathconf(vp, uap->name, retval, vfs_context_current());
 2709 
 2710                         (void)vnode_put(vp);
 2711                 }
 2712                 goto out;
 2713 
 2714         case DTYPE_PSXSHM:
 2715         case DTYPE_PSXSEM:
 2716         case DTYPE_KQUEUE:
 2717         case DTYPE_FSEVENTS:
 2718                 error = EINVAL;
 2719                 goto out;
 2720 
 2721         }
 2722         /*NOTREACHED*/
 2723 out:
 2724         fp_drop(p, fd, fp, 0);
 2725         return(error);
 2726 }
 2727 
 2728 /*
 2729  * Statistics counter for the number of times a process calling fdalloc()
 2730  * has resulted in an expansion of the per process open file table.
 2731  *
 2732  * XXX This would likely be of more use if it were per process
 2733  */
 2734 int fdexpand;
 2735 
 2736 
 2737 /*
 2738  * fdalloc
 2739  *
 2740  * Description: Allocate a file descriptor for the process.
 2741  *
 2742  * Parameters:  p                               Process to allocate the fd in
 2743  *              want                            The fd we would prefer to get
 2744  *              result                          Pointer to fd we got
 2745  *
 2746  * Returns:     0                               Success
 2747  *              EMFILE
 2748  *              ENOMEM
 2749  *
 2750  * Implicit returns:
 2751  *              *result (modified)              The fd which was allocated
 2752  */
 2753 int
 2754 fdalloc(proc_t p, int want, int *result)
 2755 {
 2756         struct filedesc *fdp = p->p_fd;
 2757         int i;
 2758         int lim, last, numfiles, oldnfiles;
 2759         struct fileproc **newofiles, **ofiles;
 2760         char *newofileflags;
 2761 
 2762         /*
 2763          * Search for a free descriptor starting at the higher
 2764          * of want or fd_freefile.  If that fails, consider
 2765          * expanding the ofile array.
 2766          */
 2767 #if DIAGNOSTIC
 2768         proc_fdlock_assert(p, LCK_MTX_ASSERT_OWNED);
 2769 #endif
 2770 
 2771         lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
 2772         for (;;) {
 2773                 last = min(fdp->fd_nfiles, lim);
 2774                 if ((i = want) < fdp->fd_freefile)
 2775                         i = fdp->fd_freefile;
 2776                 for (; i < last; i++) {
 2777                         if (fdp->fd_ofiles[i] == NULL && !(fdp->fd_ofileflags[i] & UF_RESERVED)) {
 2778                                 procfdtbl_reservefd(p, i);
 2779                                 if (i > fdp->fd_lastfile)
 2780                                         fdp->fd_lastfile = i;
 2781                                 if (want <= fdp->fd_freefile)
 2782                                         fdp->fd_freefile = i;
 2783                                 *result = i;
 2784                                 return (0);
 2785                         }
 2786                 }
 2787 
 2788                 /*
 2789                  * No space in current array.  Expand?
 2790                  */
 2791                 if (fdp->fd_nfiles >= lim)
 2792                         return (EMFILE);
 2793                 if (fdp->fd_nfiles < NDEXTENT)
 2794                         numfiles = NDEXTENT;
 2795                 else
 2796                         numfiles = 2 * fdp->fd_nfiles;
 2797                 /* Enforce lim */
 2798                 if (numfiles > lim)
 2799                         numfiles = lim;
 2800                 proc_fdunlock(p);
 2801                 MALLOC_ZONE(newofiles, struct fileproc **,
 2802                                 numfiles * OFILESIZE, M_OFILETABL, M_WAITOK);
 2803                 proc_fdlock(p);
 2804                 if (newofiles == NULL) {
 2805                         return (ENOMEM);
 2806                 }
 2807                 if (fdp->fd_nfiles >= numfiles) {
 2808                         FREE_ZONE(newofiles, numfiles * OFILESIZE, M_OFILETABL);
 2809                         continue;
 2810                 }
 2811                 newofileflags = (char *) &newofiles[numfiles];
 2812                 /*
 2813                  * Copy the existing ofile and ofileflags arrays
 2814                  * and zero the new portion of each array.
 2815                  */
 2816                 oldnfiles = fdp->fd_nfiles;
 2817                 (void) memcpy(newofiles, fdp->fd_ofiles,
 2818                                 oldnfiles * sizeof(*fdp->fd_ofiles));
 2819                 (void) memset(&newofiles[oldnfiles], 0,
 2820                                 (numfiles - oldnfiles) * sizeof(*fdp->fd_ofiles));
 2821 
 2822                 (void) memcpy(newofileflags, fdp->fd_ofileflags,
 2823                                 oldnfiles * sizeof(*fdp->fd_ofileflags));
 2824                 (void) memset(&newofileflags[oldnfiles], 0,
 2825                                 (numfiles - oldnfiles) *
 2826                                                 sizeof(*fdp->fd_ofileflags));
 2827                 ofiles = fdp->fd_ofiles;
 2828                 fdp->fd_ofiles = newofiles;
 2829                 fdp->fd_ofileflags = newofileflags;
 2830                 fdp->fd_nfiles = numfiles;
 2831                 FREE_ZONE(ofiles, oldnfiles * OFILESIZE, M_OFILETABL);
 2832                 fdexpand++;
 2833         }
 2834 }
 2835 
 2836 
 2837 /*
 2838  * fdavail
 2839  *
 2840  * Description: Check to see whether n user file descriptors are available
 2841  *              to the process p.
 2842  *
 2843  * Parameters:  p                               Process to check in
 2844  *              n                               The number of fd's desired
 2845  *
 2846  * Returns:     0                               No
 2847  *              1                               Yes
 2848  *
 2849  * Locks:       Assumes proc_fdlock for process is held by the caller
 2850  *
 2851  * Notes:       The answer only remains valid so long as the proc_fdlock is
 2852  *              held by the caller.
 2853  */
 2854 int
 2855 fdavail(proc_t p, int n)
 2856 {
 2857         struct filedesc *fdp = p->p_fd;
 2858         struct fileproc **fpp;
 2859         char *flags;
 2860         int i, lim;
 2861 
 2862         lim = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
 2863         if ((i = lim - fdp->fd_nfiles) > 0 && (n -= i) <= 0)
 2864                 return (1);
 2865         fpp = &fdp->fd_ofiles[fdp->fd_freefile];
 2866         flags = &fdp->fd_ofileflags[fdp->fd_freefile];
 2867         for (i = fdp->fd_nfiles - fdp->fd_freefile; --i >= 0; fpp++, flags++)
 2868                 if (*fpp == NULL && !(*flags & UF_RESERVED) && --n <= 0)
 2869                         return (1);
 2870         return (0);
 2871 }
 2872 
 2873 
 2874 /*
 2875  * fdrelse
 2876  *
 2877  * Description: Legacy KPI wrapper function for _fdrelse
 2878  *
 2879  * Parameters:  p                               Process in which fd lives
 2880  *              fd                              fd to free
 2881  *
 2882  * Returns:     void
 2883  *
 2884  * Locks:       Assumes proc_fdlock for process is held by the caller
 2885  */
 2886 void
 2887 fdrelse(proc_t p, int fd)
 2888 {
 2889         _fdrelse(p, fd);
 2890 }
 2891 
 2892 
 2893 /*
 2894  * fdgetf_noref
 2895  *
 2896  * Description: Get the fileproc pointer for the given fd from the per process
 2897  *              open file table without taking an explicit reference on it.
 2898  *
 2899  * Parameters:  p                               Process containing fd
 2900  *              fd                              fd to obtain fileproc for
 2901  *              resultfp                        Pointer to pointer return area
 2902  *
 2903  * Returns:     0                               Success
 2904  *              EBADF
 2905  *
 2906  * Implicit returns:
 2907  *              *resultfp (modified)            Pointer to fileproc pointer
 2908  *
 2909  * Locks:       Assumes proc_fdlock for process is held by the caller
 2910  *
 2911  * Notes:       Because there is no reference explicitly taken, the returned
 2912  *              fileproc pointer is only valid so long as the proc_fdlock
 2913  *              remains held by the caller.
 2914  */
 2915 int
 2916 fdgetf_noref(proc_t p, int fd, struct fileproc **resultfp)
 2917 {
 2918         struct filedesc *fdp = p->p_fd;
 2919         struct fileproc *fp;
 2920 
 2921         if (fd < 0 || fd >= fdp->fd_nfiles ||
 2922                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 2923                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 2924                 return (EBADF);
 2925         }
 2926         if (resultfp)
 2927                 *resultfp = fp;
 2928         return (0);
 2929 }
 2930 
 2931 
 2932 /*
 2933  * fp_getfvp
 2934  *
 2935  * Description: Get fileproc and vnode pointer for a given fd from the per
 2936  *              process open file table of the specified process, and if
 2937  *              successful, increment the f_iocount
 2938  *
 2939  * Parameters:  p                               Process in which fd lives
 2940  *              fd                              fd to get information for
 2941  *              resultfp                        Pointer to result fileproc
 2942  *                                              pointer area, or 0 if none
 2943  *              resultvp                        Pointer to result vnode pointer
 2944  *                                              area, or 0 if none
 2945  *
 2946  * Returns:     0                               Success
 2947  *              EBADF                           Bad file descriptor
 2948  *              ENOTSUP                         fd does not refer to a vnode
 2949  *
 2950  * Implicit returns:
 2951  *              *resultfp (modified)            Fileproc pointer
 2952  *              *resultvp (modified)            vnode pointer
 2953  *
 2954  * Notes:       The resultfp and resultvp fields are optional, and may be
 2955  *              independently specified as NULL to skip returning information
 2956  *
 2957  * Locks:       Internally takes and releases proc_fdlock
 2958  */
 2959 int
 2960 fp_getfvp(proc_t p, int fd, struct fileproc **resultfp, struct vnode **resultvp)
 2961 {
 2962         struct filedesc *fdp = p->p_fd;
 2963         struct fileproc *fp;
 2964 
 2965         proc_fdlock_spin(p);
 2966         if (fd < 0 || fd >= fdp->fd_nfiles ||
 2967                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 2968                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 2969                 proc_fdunlock(p);
 2970                 return (EBADF);
 2971         }
 2972         if (fp->f_type != DTYPE_VNODE) {
 2973                 proc_fdunlock(p);
 2974                 return(ENOTSUP);
 2975         }
 2976         fp->f_iocount++;
 2977 
 2978         if (resultfp)
 2979                 *resultfp = fp;
 2980         if (resultvp)
 2981                 *resultvp = (struct vnode *)fp->f_data;
 2982         proc_fdunlock(p);
 2983 
 2984         return (0);
 2985 }
 2986 
 2987 
 2988 /*
 2989  * fp_getfvpandvid
 2990  *
 2991  * Description: Get fileproc, vnode pointer, and vid for a given fd from the
 2992  *              per process open file table of the specified process, and if
 2993  *              successful, increment the f_iocount
 2994  *
 2995  * Parameters:  p                               Process in which fd lives
 2996  *              fd                              fd to get information for
 2997  *              resultfp                        Pointer to result fileproc
 2998  *                                              pointer area, or 0 if none
 2999  *              resultvp                        Pointer to result vnode pointer
 3000  *                                              area, or 0 if none
 3001  *              vidp                            Pointer to resuld vid area
 3002  *
 3003  * Returns:     0                               Success
 3004  *              EBADF                           Bad file descriptor
 3005  *              ENOTSUP                         fd does not refer to a vnode
 3006  *
 3007  * Implicit returns:
 3008  *              *resultfp (modified)            Fileproc pointer
 3009  *              *resultvp (modified)            vnode pointer
 3010  *              *vidp                           vid value
 3011  *
 3012  * Notes:       The resultfp and resultvp fields are optional, and may be
 3013  *              independently specified as NULL to skip returning information
 3014  *
 3015  * Locks:       Internally takes and releases proc_fdlock
 3016  */
 3017 int
 3018 fp_getfvpandvid(proc_t p, int fd, struct fileproc **resultfp,
 3019                 struct vnode **resultvp, uint32_t *vidp)
 3020 {
 3021         struct filedesc *fdp = p->p_fd;
 3022         struct fileproc *fp;
 3023 
 3024         proc_fdlock_spin(p);
 3025         if (fd < 0 || fd >= fdp->fd_nfiles ||
 3026                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 3027                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 3028                 proc_fdunlock(p);
 3029                 return (EBADF);
 3030         }
 3031         if (fp->f_type != DTYPE_VNODE) {
 3032                 proc_fdunlock(p);
 3033                 return(ENOTSUP);
 3034         }
 3035         fp->f_iocount++;
 3036 
 3037         if (resultfp)
 3038                 *resultfp = fp;
 3039         if (resultvp)
 3040                 *resultvp = (struct vnode *)fp->f_data;
 3041         if (vidp)
 3042                 *vidp = (uint32_t)vnode_vid((struct vnode *)fp->f_data);
 3043         proc_fdunlock(p);
 3044 
 3045         return (0);
 3046 }
 3047 
 3048 
 3049 /*
 3050  * fp_getfsock
 3051  *
 3052  * Description: Get fileproc and socket pointer for a given fd from the
 3053  *              per process open file table of the specified process, and if
 3054  *              successful, increment the f_iocount
 3055  *
 3056  * Parameters:  p                               Process in which fd lives
 3057  *              fd                              fd to get information for
 3058  *              resultfp                        Pointer to result fileproc
 3059  *                                              pointer area, or 0 if none
 3060  *              results                         Pointer to result socket
 3061  *                                              pointer area, or 0 if none
 3062  *
 3063  * Returns:     EBADF                   The file descriptor is invalid
 3064  *              EOPNOTSUPP              The file descriptor is not a socket
 3065  *              0                       Success
 3066  *
 3067  * Implicit returns:
 3068  *              *resultfp (modified)            Fileproc pointer
 3069  *              *results (modified)             socket pointer
 3070  *
 3071  * Notes:       EOPNOTSUPP should probably be ENOTSOCK; this function is only
 3072  *              ever called from accept1().
 3073  */
 3074 int
 3075 fp_getfsock(proc_t p, int fd, struct fileproc **resultfp,
 3076             struct socket **results)
 3077 {
 3078         struct filedesc *fdp = p->p_fd;
 3079         struct fileproc *fp;
 3080 
 3081         proc_fdlock_spin(p);
 3082         if (fd < 0 || fd >= fdp->fd_nfiles ||
 3083                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 3084                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 3085                 proc_fdunlock(p);
 3086                 return (EBADF);
 3087         }
 3088         if (fp->f_type != DTYPE_SOCKET) {
 3089                 proc_fdunlock(p);
 3090                 return(EOPNOTSUPP);
 3091         }
 3092         fp->f_iocount++;
 3093 
 3094         if (resultfp)
 3095                 *resultfp = fp;
 3096         if (results)
 3097                 *results = (struct socket *)fp->f_data;
 3098         proc_fdunlock(p);
 3099 
 3100         return (0);
 3101 }
 3102 
 3103 
 3104 /*
 3105  * fp_getfkq
 3106  *
 3107  * Description: Get fileproc and kqueue pointer for a given fd from the
 3108  *              per process open file table of the specified process, and if
 3109  *              successful, increment the f_iocount
 3110  *
 3111  * Parameters:  p                               Process in which fd lives
 3112  *              fd                              fd to get information for
 3113  *              resultfp                        Pointer to result fileproc
 3114  *                                              pointer area, or 0 if none
 3115  *              resultkq                        Pointer to result kqueue
 3116  *                                              pointer area, or 0 if none
 3117  *
 3118  * Returns:     EBADF                   The file descriptor is invalid
 3119  *              EBADF                   The file descriptor is not a socket
 3120  *              0                       Success
 3121  *
 3122  * Implicit returns:
 3123  *              *resultfp (modified)            Fileproc pointer
 3124  *              *resultkq (modified)            kqueue pointer
 3125  *
 3126  * Notes:       The second EBADF should probably be something else to make
 3127  *              the error condition distinct.
 3128  */
 3129 int
 3130 fp_getfkq(proc_t p, int fd, struct fileproc **resultfp,
 3131           struct kqueue **resultkq)
 3132 {
 3133         struct filedesc *fdp = p->p_fd;
 3134         struct fileproc *fp;
 3135 
 3136         proc_fdlock_spin(p);
 3137         if ( fd < 0 || fd >= fdp->fd_nfiles ||
 3138                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 3139                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 3140                 proc_fdunlock(p);
 3141                 return (EBADF);
 3142         }
 3143         if (fp->f_type != DTYPE_KQUEUE) {
 3144                 proc_fdunlock(p);
 3145                 return(EBADF);
 3146         }
 3147         fp->f_iocount++;
 3148 
 3149         if (resultfp)
 3150                 *resultfp = fp;
 3151         if (resultkq)
 3152                 *resultkq = (struct kqueue *)fp->f_data;
 3153         proc_fdunlock(p);
 3154 
 3155         return (0);
 3156 }
 3157 
 3158 
 3159 /*
 3160  * fp_getfpshm
 3161  *
 3162  * Description: Get fileproc and POSIX shared memory pointer for a given fd
 3163  *              from the per process open file table of the specified process
 3164  *              and if successful, increment the f_iocount
 3165  *
 3166  * Parameters:  p                               Process in which fd lives
 3167  *              fd                              fd to get information for
 3168  *              resultfp                        Pointer to result fileproc
 3169  *                                              pointer area, or 0 if none
 3170  *              resultpshm                      Pointer to result POSIX
 3171  *                                              shared memory pointer
 3172  *                                              pointer area, or 0 if none
 3173  *
 3174  * Returns:     EBADF                   The file descriptor is invalid
 3175  *              EBADF                   The file descriptor is not a POSIX
 3176  *                                      shared memory area
 3177  *              0                       Success
 3178  *
 3179  * Implicit returns:
 3180  *              *resultfp (modified)            Fileproc pointer
 3181  *              *resultpshm (modified)          POSIX shared memory pointer
 3182  *
 3183  * Notes:       The second EBADF should probably be something else to make
 3184  *              the error condition distinct.
 3185  */
 3186 int
 3187 fp_getfpshm(proc_t p, int fd, struct fileproc **resultfp,
 3188             struct pshmnode **resultpshm)
 3189 {
 3190         struct filedesc *fdp = p->p_fd;
 3191         struct fileproc *fp;
 3192 
 3193         proc_fdlock_spin(p);
 3194         if (fd < 0 || fd >= fdp->fd_nfiles ||
 3195                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 3196                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 3197                 proc_fdunlock(p);
 3198                 return (EBADF);
 3199         }
 3200         if (fp->f_type != DTYPE_PSXSHM) {
 3201 
 3202                 proc_fdunlock(p);
 3203                 return(EBADF);
 3204         }
 3205         fp->f_iocount++;
 3206 
 3207         if (resultfp)
 3208                 *resultfp = fp;
 3209         if (resultpshm)
 3210                 *resultpshm = (struct pshmnode *)fp->f_data;
 3211         proc_fdunlock(p);
 3212 
 3213         return (0);
 3214 }
 3215 
 3216 
 3217 /*
 3218  * fp_getfsem
 3219  *
 3220  * Description: Get fileproc and POSIX semaphore pointer for a given fd from
 3221  *              the per process open file table of the specified process
 3222  *              and if successful, increment the f_iocount
 3223  *
 3224  * Parameters:  p                               Process in which fd lives
 3225  *              fd                              fd to get information for
 3226  *              resultfp                        Pointer to result fileproc
 3227  *                                              pointer area, or 0 if none
 3228  *              resultpsem                      Pointer to result POSIX
 3229  *                                              semaphore pointer area, or
 3230  *                                              0 if none
 3231  *
 3232  * Returns:     EBADF                   The file descriptor is invalid
 3233  *              EBADF                   The file descriptor is not a POSIX
 3234  *                                      semaphore
 3235  *              0                       Success
 3236  *
 3237  * Implicit returns:
 3238  *              *resultfp (modified)            Fileproc pointer
 3239  *              *resultpsem (modified)          POSIX semaphore pointer
 3240  *
 3241  * Notes:       The second EBADF should probably be something else to make
 3242  *              the error condition distinct.
 3243  *
 3244  *              In order to support unnamed POSIX semaphores, the named
 3245  *              POSIX semaphores will have to move out of the per-process
 3246  *              open filetable, and into a global table that is shared with
 3247  *              unnamed POSIX semaphores, since unnamed POSIX semaphores
 3248  *              are typically used by declaring instances in shared memory,
 3249  *              and there's no other way to do this without changing the
 3250  *              underlying type, which would introduce binary compatibility
 3251  *              issues.
 3252  */
 3253 int
 3254 fp_getfpsem(proc_t p, int fd, struct fileproc **resultfp,
 3255             struct psemnode **resultpsem)
 3256 {
 3257         struct filedesc *fdp = p->p_fd;
 3258         struct fileproc *fp;
 3259 
 3260         proc_fdlock_spin(p);
 3261         if (fd < 0 || fd >= fdp->fd_nfiles ||
 3262                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 3263                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 3264                 proc_fdunlock(p);
 3265                 return (EBADF);
 3266         }
 3267         if (fp->f_type != DTYPE_PSXSEM) {
 3268                 proc_fdunlock(p);
 3269                 return(EBADF);
 3270         }
 3271         fp->f_iocount++;
 3272 
 3273         if (resultfp)
 3274                 *resultfp = fp;
 3275         if (resultpsem)
 3276                 *resultpsem = (struct psemnode *)fp->f_data;
 3277         proc_fdunlock(p);
 3278 
 3279         return (0);
 3280 }
 3281 
 3282 
 3283 /*
 3284  * fp_getfpipe
 3285  *
 3286  * Description: Get fileproc and pipe pointer for a given fd from the
 3287  *              per process open file table of the specified process
 3288  *              and if successful, increment the f_iocount
 3289  *
 3290  * Parameters:  p                               Process in which fd lives
 3291  *              fd                              fd to get information for
 3292  *              resultfp                        Pointer to result fileproc
 3293  *                                              pointer area, or 0 if none
 3294  *              resultpipe                      Pointer to result pipe
 3295  *                                              pointer area, or 0 if none
 3296  *
 3297  * Returns:     EBADF                   The file descriptor is invalid
 3298  *              EBADF                   The file descriptor is not a socket
 3299  *              0                       Success
 3300  *
 3301  * Implicit returns:
 3302  *              *resultfp (modified)            Fileproc pointer
 3303  *              *resultpipe (modified)          pipe pointer
 3304  *
 3305  * Notes:       The second EBADF should probably be something else to make
 3306  *              the error condition distinct.
 3307  */
 3308 int
 3309 fp_getfpipe(proc_t p, int fd, struct fileproc **resultfp,
 3310             struct pipe **resultpipe)
 3311 {
 3312         struct filedesc *fdp = p->p_fd;
 3313         struct fileproc *fp;
 3314 
 3315         proc_fdlock_spin(p);
 3316         if (fd < 0 || fd >= fdp->fd_nfiles ||
 3317                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 3318                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 3319                 proc_fdunlock(p);
 3320                 return (EBADF);
 3321         }
 3322         if (fp->f_type != DTYPE_PIPE) {
 3323                 proc_fdunlock(p);
 3324                 return(EBADF);
 3325         }
 3326         fp->f_iocount++;
 3327 
 3328         if (resultfp)
 3329                 *resultfp = fp;
 3330         if (resultpipe)
 3331                 *resultpipe = (struct pipe *)fp->f_data;
 3332         proc_fdunlock(p);
 3333 
 3334         return (0);
 3335 }
 3336 
 3337 #if NETAT
 3338 #define DTYPE_ATALK -1          /* XXX This does not belong here */
 3339 
 3340 
 3341 /*
 3342  * fp_getfatalk
 3343  *
 3344  * Description: Get fileproc and atalk pointer for a given fd from the
 3345  *              per process open file table of the specified process
 3346  *              and if successful, increment the f_iocount
 3347  *
 3348  * Parameters:  p                               Process in which fd lives
 3349  *              fd                              fd to get information for
 3350  *              resultfp                        Pointer to result fileproc
 3351  *                                              pointer area, or 0 if none
 3352  *              resultatalk                     Pointer to result atalk
 3353  *                                              pointer area, or 0 if none
 3354  * Returns:     EBADF                   The file descriptor is invalid
 3355  *              EBADF                   The file descriptor is not a socket
 3356  *              0                       Success
 3357  *
 3358  * Implicit returns:
 3359  *              *resultfp (modified)            Fileproc pointer
 3360  *              *resultatalk (modified)         atalk pointer
 3361  *
 3362  * Notes:       The second EBADF should probably be something else to make
 3363  *              the error condition distinct.
 3364  *
 3365  *              XXX This code is specific to AppleTalk protocol support, and
 3366  *              XXX should be conditionally compiled
 3367  */
 3368 int
 3369 fp_getfatalk(proc_t p, int fd, struct fileproc **resultfp,
 3370              struct atalk **resultatalk)
 3371 {
 3372         struct filedesc *fdp = p->p_fd;
 3373         struct fileproc *fp;
 3374 
 3375         proc_fdlock_spin(p);
 3376         if (fd < 0 || fd >= fdp->fd_nfiles ||
 3377                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 3378                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 3379                 proc_fdunlock(p);
 3380                 return (EBADF);
 3381         }
 3382         if (fp->f_type != (DTYPE_ATALK+1)) {
 3383                 proc_fdunlock(p);
 3384                 return(EBADF);
 3385         }
 3386         fp->f_iocount++;
 3387 
 3388         if (resultfp)
 3389                 *resultfp = fp;
 3390         if (resultatalk)
 3391                 *resultatalk = (struct atalk *)fp->f_data;
 3392         proc_fdunlock(p);
 3393 
 3394         return (0);
 3395 }
 3396 
 3397 #endif /* NETAT */
 3398 
 3399 /*
 3400  * fp_lookup
 3401  *
 3402  * Description: Get fileproc pointer for a given fd from the per process
 3403  *              open file table of the specified process and if successful,
 3404  *              increment the f_iocount
 3405  *
 3406  * Parameters:  p                               Process in which fd lives
 3407  *              fd                              fd to get information for
 3408  *              resultfp                        Pointer to result fileproc
 3409  *                                              pointer area, or 0 if none
 3410  *              locked                          !0 if the caller holds the
 3411  *                                              proc_fdlock, 0 otherwise
 3412  *
 3413  * Returns:     0                       Success
 3414  *              EBADF                   Bad file descriptor
 3415  *
 3416  * Implicit returns:
 3417  *              *resultfp (modified)            Fileproc pointer
 3418  *
 3419  * Locks:       If the argument 'locked' is non-zero, then the caller is
 3420  *              expected to have taken and held the proc_fdlock; if it is
 3421  *              zero, than this routine internally takes and drops this lock.
 3422  */
 3423 int
 3424 fp_lookup(proc_t p, int fd, struct fileproc **resultfp, int locked)
 3425 {
 3426         struct filedesc *fdp = p->p_fd;
 3427         struct fileproc *fp;
 3428 
 3429         if (!locked)
 3430                 proc_fdlock_spin(p);
 3431         if (fd < 0 || fdp == NULL || fd >= fdp->fd_nfiles ||
 3432                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 3433                         (fdp->fd_ofileflags[fd] & UF_RESERVED)) {
 3434                 if (!locked)
 3435                         proc_fdunlock(p);
 3436                 return (EBADF);
 3437         }
 3438         fp->f_iocount++;
 3439 
 3440         if (resultfp)
 3441                 *resultfp = fp;
 3442         if (!locked)
 3443                 proc_fdunlock(p);
 3444                 
 3445         return (0);
 3446 }
 3447 
 3448 
 3449 /*
 3450  * fp_drop_written
 3451  *
 3452  * Description: Set the FP_WRITTEN flag on the fileproc and drop the I/O
 3453  *              reference previously taken by calling fp_lookup et. al.
 3454  *
 3455  * Parameters:  p                               Process in which the fd lives
 3456  *              fd                              fd associated with the fileproc
 3457  *              fp                              fileproc on which to set the
 3458  *                                              flag and drop the reference
 3459  *
 3460  * Returns:     0                               Success
 3461  *      fp_drop:EBADF                           Bad file descriptor
 3462  *
 3463  * Locks:       This function internally takes and drops the proc_fdlock for
 3464  *              the supplied process
 3465  *
 3466  * Notes:       The fileproc must correspond to the fd in the supplied proc
 3467  */
 3468 int
 3469 fp_drop_written(proc_t p, int fd, struct fileproc *fp)
 3470 {
 3471         int error;
 3472 
 3473         proc_fdlock_spin(p);
 3474 
 3475         fp->f_flags |= FP_WRITTEN;
 3476         
 3477         error = fp_drop(p, fd, fp, 1);
 3478 
 3479         proc_fdunlock(p);
 3480                 
 3481         return (error);
 3482 }
 3483 
 3484 
 3485 /*
 3486  * fp_drop_event
 3487  *
 3488  * Description: Set the FP_WAITEVENT flag on the fileproc and drop the I/O
 3489  *              reference previously taken by calling fp_lookup et. al.
 3490  *
 3491  * Parameters:  p                               Process in which the fd lives
 3492  *              fd                              fd associated with the fileproc
 3493  *              fp                              fileproc on which to set the
 3494  *                                              flag and drop the reference
 3495  *
 3496  * Returns:     0                               Success
 3497  *      fp_drop:EBADF                           Bad file descriptor
 3498  *
 3499  * Locks:       This function internally takes and drops the proc_fdlock for
 3500  *              the supplied process
 3501  *
 3502  * Notes:       The fileproc must correspond to the fd in the supplied proc
 3503  */
 3504 int
 3505 fp_drop_event(proc_t p, int fd, struct fileproc *fp)
 3506 {
 3507         int error;
 3508 
 3509         proc_fdlock_spin(p);
 3510 
 3511         fp->f_flags |= FP_WAITEVENT;
 3512         
 3513         error = fp_drop(p, fd, fp, 1);
 3514 
 3515         proc_fdunlock(p);
 3516                 
 3517         return (error);
 3518 }
 3519 
 3520 
 3521 /*
 3522  * fp_drop
 3523  *
 3524  * Description: Drop the I/O reference previously taken by calling fp_lookup
 3525  *              et. al.
 3526  *
 3527  * Parameters:  p                               Process in which the fd lives
 3528  *              fd                              fd associated with the fileproc
 3529  *              fp                              fileproc on which to set the
 3530  *                                              flag and drop the reference
 3531  *              locked                          flag to internally take and
 3532  *                                              drop proc_fdlock if it is not
 3533  *                                              already held by the caller
 3534  *
 3535  * Returns:     0                               Success
 3536  *              EBADF                           Bad file descriptor
 3537  *
 3538  * Locks:       This function internally takes and drops the proc_fdlock for
 3539  *              the supplied process if 'locked' is non-zero, and assumes that
 3540  *              the caller already holds this lock if 'locked' is non-zero.
 3541  *
 3542  * Notes:       The fileproc must correspond to the fd in the supplied proc
 3543  */
 3544 int
 3545 fp_drop(proc_t p, int fd, struct fileproc *fp, int locked)
 3546 {
 3547         struct filedesc *fdp = p->p_fd;
 3548         int     needwakeup = 0;
 3549 
 3550         if (!locked)
 3551                 proc_fdlock_spin(p);
 3552          if ((fp == FILEPROC_NULL) && (fd < 0 || fd >= fdp->fd_nfiles ||
 3553                         (fp = fdp->fd_ofiles[fd]) == NULL ||
 3554                         ((fdp->fd_ofileflags[fd] & UF_RESERVED) &&
 3555                          !(fdp->fd_ofileflags[fd] & UF_CLOSING)))) {
 3556                 if (!locked)
 3557                         proc_fdunlock(p);
 3558                 return (EBADF);
 3559         }
 3560         fp->f_iocount--;
 3561 
 3562         if (fp->f_iocount == 0) {
 3563                 if (fp->f_flags & FP_SELCONFLICT)
 3564                         fp->f_flags &= ~FP_SELCONFLICT;
 3565 
 3566                 if (p->p_fpdrainwait) {
 3567                         p->p_fpdrainwait = 0;
 3568                         needwakeup = 1;
 3569                 }
 3570         }
 3571         if (!locked)
 3572                 proc_fdunlock(p);
 3573         if (needwakeup)
 3574                 wakeup(&p->p_fpdrainwait);
 3575                 
 3576         return (0);
 3577 }
 3578 
 3579 
 3580 /*
 3581  * file_vnode
 3582  *
 3583  * Description: Given an fd, look it up in the current process's per process
 3584  *              open file table, and return its internal vnode pointer.
 3585  *
 3586  * Parameters:  fd                              fd to obtain vnode from
 3587  *              vpp                             pointer to vnode return area
 3588  *
 3589  * Returns:     0                               Success
 3590  *              EINVAL                          The fd does not refer to a
 3591  *                                              vnode fileproc entry
 3592  *      fp_lookup:EBADF                         Bad file descriptor
 3593  *
 3594  * Implicit returns:
 3595  *              *vpp (modified)                 Returned vnode pointer
 3596  *
 3597  * Locks:       This function internally takes and drops the proc_fdlock for
 3598  *              the current process
 3599  *
 3600  * Notes:       If successful, this function increments the f_iocount on the
 3601  *              fd's corresponding fileproc.
 3602  *
 3603  *              The fileproc referenced is not returned; because of this, care
 3604  *              must be taken to not drop the last reference (e.g. by closing
 3605  *              the file).  This is inherently unsafe, since the reference may
 3606  *              not be recoverable from the vnode, if there is a subsequent
 3607  *              close that destroys the associate fileproc.  The caller should
 3608  *              therefore retain their own reference on the fileproc so that
 3609  *              the f_iocount can be dropped subsequently.  Failure to do this
 3610  *              can result in the returned pointer immediately becoming invalid
 3611  *              following the call.
 3612  *
 3613  *              Use of this function is discouraged.
 3614  */
 3615 int
 3616 file_vnode(int fd, struct vnode **vpp)
 3617 {
 3618         proc_t p = current_proc();
 3619         struct fileproc *fp;
 3620         int error;
 3621         
 3622         proc_fdlock_spin(p);
 3623         if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
 3624                 proc_fdunlock(p);
 3625                 return(error);
 3626         }
 3627         if (fp->f_type != DTYPE_VNODE) {
 3628                 fp_drop(p, fd, fp,1);
 3629                 proc_fdunlock(p);
 3630                 return(EINVAL);
 3631         }
 3632         if (vpp != NULL)
 3633                 *vpp = (struct vnode *)fp->f_data;
 3634         proc_fdunlock(p);
 3635 
 3636         return(0);
 3637 }
 3638 
 3639 
 3640 /*
 3641  * file_vnode_withvid
 3642  *
 3643  * Description: Given an fd, look it up in the current process's per process
 3644  *              open file table, and return its internal vnode pointer.
 3645  *
 3646  * Parameters:  fd                              fd to obtain vnode from
 3647  *              vpp                             pointer to vnode return area
 3648  *              vidp                            pointer to vid of the returned vnode
 3649  *
 3650  * Returns:     0                               Success
 3651  *              EINVAL                          The fd does not refer to a
 3652  *                                              vnode fileproc entry
 3653  *      fp_lookup:EBADF                         Bad file descriptor
 3654  *
 3655  * Implicit returns:
 3656  *              *vpp (modified)                 Returned vnode pointer
 3657  *
 3658  * Locks:       This function internally takes and drops the proc_fdlock for
 3659  *              the current process
 3660  *
 3661  * Notes:       If successful, this function increments the f_iocount on the
 3662  *              fd's corresponding fileproc.
 3663  *
 3664  *              The fileproc referenced is not returned; because of this, care
 3665  *              must be taken to not drop the last reference (e.g. by closing
 3666  *              the file).  This is inherently unsafe, since the reference may
 3667  *              not be recoverable from the vnode, if there is a subsequent
 3668  *              close that destroys the associate fileproc.  The caller should
 3669  *              therefore retain their own reference on the fileproc so that
 3670  *              the f_iocount can be dropped subsequently.  Failure to do this
 3671  *              can result in the returned pointer immediately becoming invalid
 3672  *              following the call.
 3673  *
 3674  *              Use of this function is discouraged.
 3675  */
 3676 int
 3677 file_vnode_withvid(int fd, struct vnode **vpp, uint32_t * vidp)
 3678 {
 3679         proc_t p = current_proc();
 3680         struct fileproc *fp;
 3681         vnode_t vp;
 3682         int error;
 3683         
 3684         proc_fdlock_spin(p);
 3685         if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
 3686                 proc_fdunlock(p);
 3687                 return(error);
 3688         }
 3689         if (fp->f_type != DTYPE_VNODE) {
 3690                 fp_drop(p, fd, fp,1);
 3691                 proc_fdunlock(p);
 3692                 return(EINVAL);
 3693         }
 3694         vp = (struct vnode *)fp->f_data;
 3695         if (vpp != NULL) 
 3696                 *vpp = vp;
 3697 
 3698         if ((vidp != NULL) && (vp != NULLVP)) 
 3699                 *vidp = (uint32_t)vp->v_id;
 3700 
 3701         proc_fdunlock(p);
 3702 
 3703         return(0);
 3704 }
 3705 
 3706 
 3707 /*
 3708  * file_socket
 3709  *
 3710  * Description: Given an fd, look it up in the current process's per process
 3711  *              open file table, and return its internal socket pointer.
 3712  *
 3713  * Parameters:  fd                              fd to obtain vnode from
 3714  *              sp                              pointer to socket return area
 3715  *
 3716  * Returns:     0                               Success
 3717  *              ENOTSOCK                        Not a socket
 3718  *              fp_lookup:EBADF                 Bad file descriptor
 3719  *
 3720  * Implicit returns:
 3721  *              *sp (modified)                  Returned socket pointer
 3722  *
 3723  * Locks:       This function internally takes and drops the proc_fdlock for
 3724  *              the current process
 3725  *
 3726  * Notes:       If successful, this function increments the f_iocount on the
 3727  *              fd's corresponding fileproc.
 3728  *
 3729  *              The fileproc referenced is not returned; because of this, care
 3730  *              must be taken to not drop the last reference (e.g. by closing
 3731  *              the file).  This is inherently unsafe, since the reference may
 3732  *              not be recoverable from the socket, if there is a subsequent
 3733  *              close that destroys the associate fileproc.  The caller should
 3734  *              therefore retain their own reference on the fileproc so that
 3735  *              the f_iocount can be dropped subsequently.  Failure to do this
 3736  *              can result in the returned pointer immediately becoming invalid
 3737  *              following the call.
 3738  *
 3739  *              Use of this function is discouraged.
 3740  */
 3741 int
 3742 file_socket(int fd, struct socket **sp)
 3743 {
 3744         proc_t p = current_proc();
 3745         struct fileproc *fp;
 3746         int error;
 3747         
 3748         proc_fdlock_spin(p);
 3749         if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
 3750                 proc_fdunlock(p);
 3751                 return(error);
 3752         }
 3753         if (fp->f_type != DTYPE_SOCKET) {
 3754                 fp_drop(p, fd, fp,1);
 3755                 proc_fdunlock(p);
 3756                 return(ENOTSOCK);
 3757         }
 3758         *sp = (struct socket *)fp->f_data;
 3759         proc_fdunlock(p);
 3760 
 3761         return(0);
 3762 }
 3763 
 3764 
 3765 /*
 3766  * file_flags
 3767  *
 3768  * Description: Given an fd, look it up in the current process's per process
 3769  *              open file table, and return its fileproc's flags field.
 3770  *
 3771  * Parameters:  fd                              fd whose flags are to be
 3772  *                                              retrieved
 3773  *              flags                           pointer to flags data area
 3774  *
 3775  * Returns:     0                               Success
 3776  *              ENOTSOCK                        Not a socket
 3777  *              fp_lookup:EBADF                 Bad file descriptor
 3778  *
 3779  * Implicit returns:
 3780  *              *flags (modified)               Returned flags field
 3781  *
 3782  * Locks:       This function internally takes and drops the proc_fdlock for
 3783  *              the current process
 3784  *
 3785  * Notes:       This function will internally increment and decrement the
 3786  *              f_iocount of the fileproc as part of its operation.
 3787  */
 3788 int
 3789 file_flags(int fd, int *flags)
 3790 {
 3791 
 3792         proc_t p = current_proc();
 3793         struct fileproc *fp;
 3794         int error;
 3795         
 3796         proc_fdlock_spin(p);
 3797         if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
 3798                 proc_fdunlock(p);
 3799                 return(error);
 3800         }
 3801         *flags = (int)fp->f_flag;
 3802         fp_drop(p, fd, fp,1);
 3803         proc_fdunlock(p);
 3804 
 3805         return(0);
 3806 }
 3807 
 3808 
 3809 /*
 3810  * file_drop
 3811  *
 3812  * Description: Drop an iocount reference on an fd, and wake up any waiters
 3813  *              for draining (i.e. blocked in fileproc_drain() called during
 3814  *              the last attempt to close a file).
 3815  *
 3816  * Parameters:  fd                              fd on which an ioreference is
 3817  *                                              to be dropped
 3818  *
 3819  * Returns:     0                               Success
 3820  *              EBADF                           Bad file descriptor
 3821  *
 3822  * Description: Given an fd, look it up in the current process's per process
 3823  *              open file table, and drop it's fileproc's f_iocount by one
 3824  *
 3825  * Notes:       This is intended as a corresponding operation to the functions
 3826  *              file_vnode() and file_socket() operations.
 3827  *
 3828  *              Technically, the close reference is supposed to be protected
 3829  *              by a fileproc_drain(), however, a drain will only block if
 3830  *              the fd refers to a character device, and that device has had
 3831  *              preparefileread() called on it.  If it refers to something
 3832  *              other than a character device, then the drain will occur and
 3833  *              block each close attempt, rather than merely the last close.
 3834  *
 3835  *              Since it's possible for an fd that refers to a character
 3836  *              device to have an intermediate close followed by an open to
 3837  *              cause a different file to correspond to that descriptor,
 3838  *              unless there was a cautionary reference taken on the fileproc,
 3839  *              this is an inherently unsafe function.  This happens in the
 3840  *              case where multiple fd's in a process refer to the same
 3841  *              character device (e.g. stdin/out/err pointing to a tty, etc.).
 3842  *
 3843  *              Use of this function is discouraged.
 3844  */
 3845 int 
 3846 file_drop(int fd)
 3847 {
 3848         struct fileproc *fp;
 3849         proc_t p = current_proc();
 3850         int     needwakeup = 0;
 3851 
 3852         proc_fdlock_spin(p);
 3853         if (fd < 0 || fd >= p->p_fd->fd_nfiles ||
 3854                         (fp = p->p_fd->fd_ofiles[fd]) == NULL ||
 3855                         ((p->p_fd->fd_ofileflags[fd] & UF_RESERVED) &&
 3856                          !(p->p_fd->fd_ofileflags[fd] & UF_CLOSING))) {
 3857                 proc_fdunlock(p);
 3858                 return (EBADF);
 3859         }
 3860         fp->f_iocount --;
 3861 
 3862         if (fp->f_iocount == 0) {
 3863                 if (fp->f_flags & FP_SELCONFLICT)
 3864                         fp->f_flags &= ~FP_SELCONFLICT;
 3865 
 3866                 if (p->p_fpdrainwait) {
 3867                         p->p_fpdrainwait = 0;
 3868                         needwakeup = 1;
 3869                 }
 3870         }
 3871         proc_fdunlock(p);
 3872 
 3873         if (needwakeup)
 3874                 wakeup(&p->p_fpdrainwait);
 3875         return(0);
 3876 }
 3877 
 3878 
 3879 /*
 3880  * falloc
 3881  *
 3882  * Description: Allocate an entry in the per process open file table and
 3883  *              return the corresponding fileproc and fd.
 3884  *
 3885  * Parameters:  p                               The process in whose open file
 3886  *                                              table the fd is to be allocated
 3887  *              resultfp                        Pointer to fileproc pointer
 3888  *                                              return area
 3889  *              resultfd                        Pointer to fd return area
 3890  *              ctx                             VFS context
 3891  *
 3892  * Returns:     0                               Success
 3893  *      falloc:ENFILE                           Too many open files in system
 3894  *      falloc:EMFILE                           Too many open files in process
 3895  *      falloc:ENOMEM                           M_FILEPROC or M_FILEGLOB zone
 3896  *                                              exhausted
 3897  *
 3898  * Implicit returns:
 3899  *              *resultfd (modified)            Returned fileproc pointer
 3900  *              *resultfd (modified)            Returned fd
 3901  *
 3902  * Locks:       This function takes and drops the proc_fdlock; if this lock
 3903  *              is already held, use falloc_locked() instead.
 3904  *
 3905  * Notes:       This function takes separate process and context arguments
 3906  *              solely to support kern_exec.c; otherwise, it would take
 3907  *              neither, and expect falloc_locked() to use the
 3908  *              vfs_context_current() routine internally.
 3909  */
 3910 int
 3911 falloc(proc_t p, struct fileproc **resultfp, int *resultfd, vfs_context_t ctx)
 3912 {
 3913         int error;
 3914 
 3915         proc_fdlock(p);
 3916         error = falloc_locked(p, resultfp, resultfd, ctx, 1);
 3917         proc_fdunlock(p);
 3918 
 3919         return(error);
 3920 }
 3921 
 3922 
 3923 /*
 3924  * falloc_locked
 3925  *
 3926  * Create a new open file structure and allocate
 3927  * a file descriptor for the process that refers to it.
 3928  *
 3929  * Returns:     0                       Success
 3930  *
 3931  * Description: Allocate an entry in the per process open file table and
 3932  *              return the corresponding fileproc and fd.
 3933  *
 3934  * Parameters:  p                               The process in whose open file
 3935  *                                              table the fd is to be allocated
 3936  *              resultfp                        Pointer to fileproc pointer
 3937  *                                              return area
 3938  *              resultfd                        Pointer to fd return area
 3939  *              ctx                             VFS context
 3940  *              locked                          Flag to indicate whether the
 3941  *                                              caller holds proc_fdlock
 3942  *
 3943  * Returns:     0                               Success
 3944  *              ENFILE                          Too many open files in system
 3945  *              fdalloc:EMFILE                  Too many open files in process
 3946  *              ENOMEM                          M_FILEPROC or M_FILEGLOB zone
 3947  *                                              exhausted
 3948  *      fdalloc:ENOMEM
 3949  *
 3950  * Implicit returns:
 3951  *              *resultfd (modified)            Returned fileproc pointer
 3952  *              *resultfd (modified)            Returned fd
 3953  *
 3954  * Locks:       If the parameter 'locked' is zero, this function takes and
 3955  *              drops the proc_fdlock; if non-zero, the caller must hold the
 3956  *              lock.
 3957  *
 3958  * Notes:       If you intend to use a non-zero 'locked' parameter, use the
 3959  *              utility function falloc() instead.
 3960  *
 3961  *              This function takes separate process and context arguments
 3962  *              solely to support kern_exec.c; otherwise, it would take
 3963  *              neither, and use the vfs_context_current() routine internally.
 3964  */
 3965 int
 3966 falloc_locked(proc_t p, struct fileproc **resultfp, int *resultfd,
 3967               vfs_context_t ctx, int locked)
 3968 {
 3969         struct fileproc *fp;
 3970         struct fileglob *fg;
 3971         int error, nfd;
 3972 
 3973         if (!locked)
 3974                 proc_fdlock(p);
 3975         if ( (error = fdalloc(p, 0, &nfd)) ) {
 3976                 if (!locked)
 3977                         proc_fdunlock(p);
 3978                 return (error);
 3979         }
 3980         if (nfiles >= maxfiles) {
 3981                 if (!locked)
 3982                         proc_fdunlock(p);
 3983                 tablefull("file");
 3984                 return (ENFILE);
 3985         }
 3986 #if CONFIG_MACF
 3987         error = mac_file_check_create(proc_ucred(p));
 3988         if (error) {
 3989                 if (!locked)
 3990                         proc_fdunlock(p);
 3991                 return (error);
 3992         }
 3993 #endif
 3994 
 3995         /*
 3996          * Allocate a new file descriptor.
 3997          * If the process has file descriptor zero open, add to the list
 3998          * of open files at that point, otherwise put it at the front of
 3999          * the list of open files.
 4000          */
 4001         proc_fdunlock(p);
 4002 
 4003         MALLOC_ZONE(fp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
 4004         if (fp == NULL) {
 4005                 if (locked)
 4006                         proc_fdlock(p);
 4007                 return (ENOMEM);
 4008         }
 4009         MALLOC_ZONE(fg, struct fileglob *, sizeof(struct fileglob), M_FILEGLOB, M_WAITOK);
 4010         if (fg == NULL) {
 4011                 FREE_ZONE(fp, sizeof(*fp), M_FILEPROC);
 4012                 if (locked)
 4013                         proc_fdlock(p);
 4014                 return (ENOMEM);
 4015         }
 4016         bzero(fp, sizeof(struct fileproc));
 4017         bzero(fg, sizeof(struct fileglob));
 4018         lck_mtx_init(&fg->fg_lock, file_lck_grp, file_lck_attr);
 4019 
 4020         fp->f_iocount = 1;
 4021         fg->fg_count = 1;
 4022         fp->f_fglob = fg;
 4023 #if CONFIG_MACF
 4024         mac_file_label_init(fg);
 4025 #endif
 4026 
 4027         kauth_cred_ref(ctx->vc_ucred);
 4028 
 4029         proc_fdlock(p);
 4030 
 4031         fp->f_cred = ctx->vc_ucred;
 4032 
 4033 #if CONFIG_MACF
 4034         mac_file_label_associate(fp->f_cred, fg);
 4035 #endif
 4036 
 4037         OSAddAtomic(1, &nfiles);
 4038 
 4039         p->p_fd->fd_ofiles[nfd] = fp;
 4040 
 4041         if (!locked)
 4042                 proc_fdunlock(p);
 4043 
 4044         if (resultfp)
 4045                 *resultfp = fp;
 4046         if (resultfd)
 4047                 *resultfd = nfd;
 4048 
 4049         return (0);
 4050 }
 4051 
 4052 
 4053 /*
 4054  * fg_free
 4055  *
 4056  * Description: Free a file structure; drop the global open file count, and
 4057  *              drop the credential reference, if the fileglob has one, and
 4058  *              destroy the instance mutex before freeing
 4059  *
 4060  * Parameters:  fg                              Pointer to fileglob to be
 4061  *                                              freed
 4062  *
 4063  * Returns:     void
 4064  */
 4065 void
 4066 fg_free(struct fileglob *fg)
 4067 {
 4068         OSAddAtomic(-1, &nfiles);
 4069 
 4070         if (IS_VALID_CRED(fg->fg_cred)) {
 4071                 kauth_cred_unref(&fg->fg_cred);
 4072         }
 4073         lck_mtx_destroy(&fg->fg_lock, file_lck_grp);
 4074 
 4075 #if CONFIG_MACF
 4076         mac_file_label_destroy(fg);
 4077 #endif
 4078         FREE_ZONE(fg, sizeof *fg, M_FILEGLOB);
 4079 }
 4080 
 4081 
 4082 /*
 4083  * fdexec
 4084  *
 4085  * Description: Perform close-on-exec processing for all files in a process
 4086  *              that are either marked as close-on-exec, or which were in the
 4087  *              process of being opened at the time of the execve
 4088  *
 4089  *              Also handles the case (via posix_spawn()) where -all-
 4090  *              files except those marked with "inherit" as treated as
 4091  *              close-on-exec.
 4092  *
 4093  * Parameters:  p                               Pointer to process calling
 4094  *                                              execve
 4095  *
 4096  * Returns:     void
 4097  *
 4098  * Locks:       This function internally takes and drops proc_fdlock()
 4099  *
 4100  * Notes:       This function drops and retakes the kernel funnel; this is
 4101  *              inherently unsafe, since another thread may have the
 4102  *              proc_fdlock.
 4103  *
 4104  * XXX:         We should likely reverse the lock and funnel drop/acquire
 4105  *              order to avoid the small race window; it's also possible that
 4106  *              if the program doing the exec has an outstanding listen socket
 4107  *              and a network connection is completed asynchronously that we
 4108  *              will end up with a "ghost" socket reference in the new process.
 4109  *
 4110  *              This needs reworking to make it safe to remove the funnel from
 4111  *              the execve and posix_spawn system calls.
 4112  */
 4113 void
 4114 fdexec(proc_t p, short flags)
 4115 {
 4116         struct filedesc *fdp = p->p_fd;
 4117         int i;
 4118         boolean_t cloexec_default = (flags & POSIX_SPAWN_CLOEXEC_DEFAULT) != 0;
 4119 
 4120         proc_fdlock(p);
 4121         for (i = fdp->fd_lastfile; i >= 0; i--) {
 4122 
 4123                 struct fileproc *fp = fdp->fd_ofiles[i];
 4124                 char *flagp = &fdp->fd_ofileflags[i];
 4125 
 4126                 if (fp && cloexec_default) {
 4127                         /*
 4128                          * Reverse the usual semantics of file descriptor
 4129                          * inheritance - all of them should be closed
 4130                          * except files marked explicitly as "inherit" and
 4131                          * not marked close-on-exec.
 4132                          */
 4133                         if ((*flagp & (UF_EXCLOSE|UF_INHERIT)) != UF_INHERIT)
 4134                                 *flagp |= UF_EXCLOSE;
 4135                         *flagp &= ~UF_INHERIT;
 4136                 }
 4137 
 4138                 if (
 4139                     ((*flagp & (UF_RESERVED|UF_EXCLOSE)) == UF_EXCLOSE)
 4140 #if CONFIG_MACF
 4141                     || (fp && mac_file_check_inherit(proc_ucred(p), fp->f_fglob))
 4142 #endif
 4143                 ) {
 4144                         if (i < fdp->fd_knlistsize)
 4145                                 knote_fdclose(p, i);
 4146                         procfdtbl_clearfd(p, i);
 4147                         if (i == fdp->fd_lastfile && i > 0)
 4148                                 fdp->fd_lastfile--;
 4149                         if (i < fdp->fd_freefile)
 4150                                 fdp->fd_freefile = i;
 4151 
 4152                         /*
 4153                          * Wait for any third party viewers (e.g., lsof)
 4154                          * to release their references to this fileproc.
 4155                          */
 4156                         while (fp->f_iocount > 0) {
 4157                                 p->p_fpdrainwait = 1;
 4158                                 msleep(&p->p_fpdrainwait, &p->p_fdmlock, PRIBIO,
 4159                                     "fpdrain", NULL);
 4160                         }
 4161 
 4162                         closef_locked(fp, fp->f_fglob, p);
 4163 
 4164                         FREE_ZONE(fp, sizeof(*fp), M_FILEPROC);
 4165                 }
 4166         }
 4167         proc_fdunlock(p);
 4168 }
 4169 
 4170 
 4171 /*
 4172  * fdcopy
 4173  *
 4174  * Description: Copy a filedesc structure.  This is normally used as part of
 4175  *              forkproc() when forking a new process, to copy the per process
 4176  *              open file table over to the new process.
 4177  *
 4178  * Parameters:  p                               Process whose open file table
 4179  *                                              is to be copied (parent)
 4180  *              uth_cdir                        Per thread current working
 4181  *                                              cirectory, or NULL
 4182  *
 4183  * Returns:     NULL                            Copy failed
 4184  *              !NULL                           Pointer to new struct filedesc
 4185  *
 4186  * Locks:       This function internally takes and drops proc_fdlock()
 4187  *
 4188  * Notes:       Files are copied directly, ignoring the new resource limits
 4189  *              for the process that's being copied into.  Since the descriptor
 4190  *              references are just additional references, this does not count
 4191  *              against the number of open files on the system.
 4192  *
 4193  *              The struct filedesc includes the current working directory,
 4194  *              and the current root directory, if the process is chroot'ed.
 4195  *
 4196  *              If the exec was called by a thread using a per thread current
 4197  *              working directory, we inherit the working directory from the
 4198  *              thread making the call, rather than from the process.
 4199  *
 4200  *              In the case of a failure to obtain a reference, for most cases,
 4201  *              the file entry will be silently dropped.  There's an exception
 4202  *              for the case of a chroot dir, since a failure to to obtain a
 4203  *              reference there would constitute an "escape" from the chroot
 4204  *              environment, which must not be allowed.  In that case, we will
 4205  *              deny the execve() operation, rather than allowing the escape.
 4206  */
 4207 struct filedesc *
 4208 fdcopy(proc_t p, vnode_t uth_cdir)
 4209 {
 4210         struct filedesc *newfdp, *fdp = p->p_fd;
 4211         int i;
 4212         struct fileproc *ofp, *fp;
 4213         vnode_t v_dir;
 4214 
 4215         MALLOC_ZONE(newfdp, struct filedesc *,
 4216                         sizeof(*newfdp), M_FILEDESC, M_WAITOK);
 4217         if (newfdp == NULL)
 4218                 return(NULL);
 4219 
 4220         proc_fdlock(p);
 4221 
 4222         /*
 4223          * the FD_CHROOT flag will be inherited via this copy
 4224          */
 4225         (void) memcpy(newfdp, fdp, sizeof(*newfdp));
 4226 
 4227         /*
 4228          * If we are running with per-thread current working directories,
 4229          * inherit the new current working directory from the current thread
 4230          * instead, before we take our references.
 4231          */
 4232         if (uth_cdir != NULLVP)
 4233                 newfdp->fd_cdir = uth_cdir;
 4234 
 4235         /*
 4236          * For both fd_cdir and fd_rdir make sure we get
 4237          * a valid reference... if we can't, than set
 4238          * set the pointer(s) to NULL in the child... this
 4239          * will keep us from using a non-referenced vp
 4240          * and allows us to do the vnode_rele only on
 4241          * a properly referenced vp
 4242          */
 4243         if ( (v_dir = newfdp->fd_cdir) ) {
 4244                 if (vnode_getwithref(v_dir) == 0) {
 4245                         if ( (vnode_ref(v_dir)) )
 4246                                 newfdp->fd_cdir = NULL;
 4247                         vnode_put(v_dir);
 4248                 } else
 4249                         newfdp->fd_cdir = NULL;
 4250         }
 4251         if (newfdp->fd_cdir == NULL && fdp->fd_cdir) {
 4252                 /*
 4253                  * we couldn't get a new reference on
 4254                  * the current working directory being
 4255                  * inherited... we might as well drop
 4256                  * our reference from the parent also
 4257                  * since the vnode has gone DEAD making
 4258                  * it useless... by dropping it we'll
 4259                  * be that much closer to recycling it
 4260                  */
 4261                 vnode_rele(fdp->fd_cdir);
 4262                 fdp->fd_cdir = NULL;
 4263         }
 4264 
 4265         if ( (v_dir = newfdp->fd_rdir) ) {
 4266                 if (vnode_getwithref(v_dir) == 0) {
 4267                         if ( (vnode_ref(v_dir)) )
 4268                                 newfdp->fd_rdir = NULL;
 4269                         vnode_put(v_dir);
 4270                 } else {
 4271                         newfdp->fd_rdir = NULL;
 4272                 }
 4273         }
 4274         /* Coming from a chroot environment and unable to get a reference... */
 4275         if (newfdp->fd_rdir == NULL && fdp->fd_rdir) {
 4276                 /*
 4277                  * We couldn't get a new reference on
 4278                  * the chroot directory being
 4279                  * inherited... this is fatal, since
 4280                  * otherwise it would constitute an
 4281                  * escape from a chroot environment by
 4282                  * the new process.
 4283                  */
 4284                 if (newfdp->fd_cdir)
 4285                         vnode_rele(newfdp->fd_cdir);
 4286                 FREE_ZONE(newfdp, sizeof *newfdp, M_FILEDESC);
 4287                 return(NULL);
 4288         }
 4289         newfdp->fd_refcnt = 1;
 4290 
 4291         /*
 4292          * If the number of open files fits in the internal arrays
 4293          * of the open file structure, use them, otherwise allocate
 4294          * additional memory for the number of descriptors currently
 4295          * in use.
 4296          */
 4297         if (newfdp->fd_lastfile < NDFILE)
 4298                 i = NDFILE;
 4299         else {
 4300                 /*
 4301                  * Compute the smallest multiple of NDEXTENT needed
 4302                  * for the file descriptors currently in use,
 4303                  * allowing the table to shrink.
 4304                  */
 4305                 i = newfdp->fd_nfiles;
 4306                 while (i > 2 * NDEXTENT && i > newfdp->fd_lastfile * 2)
 4307                         i /= 2;
 4308         }
 4309         proc_fdunlock(p);
 4310 
 4311         MALLOC_ZONE(newfdp->fd_ofiles, struct fileproc **,
 4312                                 i * OFILESIZE, M_OFILETABL, M_WAITOK);
 4313         if (newfdp->fd_ofiles == NULL) {
 4314                 if (newfdp->fd_cdir)
 4315                         vnode_rele(newfdp->fd_cdir);
 4316                 if (newfdp->fd_rdir)
 4317                         vnode_rele(newfdp->fd_rdir);
 4318 
 4319                 FREE_ZONE(newfdp, sizeof(*newfdp), M_FILEDESC);
 4320                 return(NULL);
 4321         }
 4322         (void) memset(newfdp->fd_ofiles, 0, i * OFILESIZE);
 4323         proc_fdlock(p);
 4324 
 4325         newfdp->fd_ofileflags = (char *) &newfdp->fd_ofiles[i];
 4326         newfdp->fd_nfiles = i;
 4327 
 4328         if (fdp->fd_nfiles > 0) {
 4329                 struct fileproc **fpp;
 4330                 char *flags;
 4331 
 4332                 (void) memcpy(newfdp->fd_ofiles, fdp->fd_ofiles,
 4333                                         (newfdp->fd_lastfile + 1) * sizeof(*fdp->fd_ofiles));
 4334                 (void) memcpy(newfdp->fd_ofileflags, fdp->fd_ofileflags,
 4335                                         (newfdp->fd_lastfile + 1) * sizeof(*fdp->fd_ofileflags));
 4336 
 4337                 /*
 4338                  * kq descriptors cannot be copied.
 4339                  */
 4340                 if (newfdp->fd_knlistsize != -1) {
 4341                         fpp = &newfdp->fd_ofiles[newfdp->fd_lastfile];
 4342                         for (i = newfdp->fd_lastfile; i >= 0; i--, fpp--) {
 4343                                 if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE) {
 4344                                         *fpp = NULL;
 4345                                         newfdp->fd_ofileflags[i] = 0;
 4346                                         if (i < newfdp->fd_freefile)
 4347                                                 newfdp->fd_freefile = i;
 4348                                 }
 4349                                 if (*fpp == NULL && i == newfdp->fd_lastfile && i > 0)
 4350                                         newfdp->fd_lastfile--;
 4351                         }
 4352                         newfdp->fd_knlist = NULL;
 4353                         newfdp->fd_knlistsize = -1;
 4354                         newfdp->fd_knhash = NULL;
 4355                         newfdp->fd_knhashmask = 0;
 4356                 }
 4357                 fpp = newfdp->fd_ofiles;
 4358                 flags = newfdp->fd_ofileflags;
 4359 
 4360                 for (i = newfdp->fd_lastfile + 1; --i >= 0; fpp++, flags++)
 4361                         if ((ofp = *fpp) != NULL && !(*flags & UF_RESERVED)) {
 4362                                 MALLOC_ZONE(fp, struct fileproc *, sizeof(struct fileproc), M_FILEPROC, M_WAITOK);
 4363                                 if (fp == NULL) {
 4364                                         /*
 4365                                          * XXX no room to copy, unable to
 4366                                          * XXX safely unwind state at present
 4367                                          */
 4368                                         *fpp = NULL;
 4369                                 } else {
 4370                                         bzero(fp, sizeof(struct fileproc));
 4371                                         fp->f_flags = ofp->f_flags;
 4372                                         //fp->f_iocount = ofp->f_iocount;
 4373                                         fp->f_iocount = 0;
 4374                                         fp->f_fglob = ofp->f_fglob;
 4375                                         (void)fg_ref(fp);
 4376                                         *fpp = fp;
 4377                                 }
 4378                         } else {
 4379                                 if (i < newfdp->fd_freefile)
 4380                                         newfdp->fd_freefile = i;
 4381                                 *fpp = NULL;
 4382                                 *flags = 0;
 4383                         }
 4384         }
 4385 
 4386         proc_fdunlock(p);
 4387         return (newfdp);
 4388 }
 4389 
 4390 
 4391 /*
 4392  * fdfree
 4393  *
 4394  * Description: Release a filedesc (per process open file table) structure;
 4395  *              this is done on process exit(), or from forkproc_free() if
 4396  *              the fork fails for some reason subsequent to a successful
 4397  *              call to fdcopy()
 4398  *
 4399  * Parameters:  p                               Pointer to process going away
 4400  *
 4401  * Returns:     void
 4402  *
 4403  * Locks:       This function internally takes and drops proc_fdlock()
 4404  */
 4405 void
 4406 fdfree(proc_t p)
 4407 {
 4408         struct filedesc *fdp;
 4409         struct fileproc *fp;
 4410         int i;
 4411 
 4412         proc_fdlock(p);
 4413 
 4414         /* Certain daemons might not have file descriptors */
 4415         fdp = p->p_fd;
 4416 
 4417         if ((fdp == NULL) || (--fdp->fd_refcnt > 0)) {
 4418                 proc_fdunlock(p);
 4419                 return;
 4420         }
 4421         if (fdp->fd_refcnt == 0xffff)
 4422                 panic("fdfree: bad fd_refcnt");
 4423 
 4424         /* Last reference: the structure can't change out from under us */
 4425 
 4426         if (fdp->fd_nfiles > 0 && fdp->fd_ofiles) {
 4427                 for (i = fdp->fd_lastfile; i >= 0; i--) {
 4428                         if ((fp = fdp->fd_ofiles[i]) != NULL) {
 4429                           
 4430                           if (fdp->fd_ofileflags[i] & UF_RESERVED)
 4431                                 panic("fdfree: found fp with UF_RESERVED");
 4432 
 4433                                 /* closef drops the iocount ... */
 4434                                 if ((fp->f_flags & FP_INCHRREAD) != 0) 
 4435                                         fp->f_iocount++;
 4436                                 procfdtbl_reservefd(p, i);
 4437 
 4438                                 if (i < fdp->fd_knlistsize)
 4439                                         knote_fdclose(p, i);
 4440                                 if (fp->f_flags & FP_WAITEVENT) 
 4441                                         (void)waitevent_close(p, fp);
 4442                                 (void) closef_locked(fp, fp->f_fglob, p);
 4443                                 FREE_ZONE(fp, sizeof(*fp), M_FILEPROC);
 4444                         }
 4445                 }
 4446                 FREE_ZONE(fdp->fd_ofiles, fdp->fd_nfiles * OFILESIZE, M_OFILETABL);
 4447                 fdp->fd_ofiles = NULL;
 4448                 fdp->fd_nfiles = 0;
 4449         }        
 4450 
 4451         proc_fdunlock(p);
 4452         
 4453         if (fdp->fd_cdir)
 4454                 vnode_rele(fdp->fd_cdir);
 4455         if (fdp->fd_rdir)
 4456                 vnode_rele(fdp->fd_rdir);
 4457 
 4458         proc_fdlock_spin(p);
 4459         p->p_fd = NULL;
 4460         proc_fdunlock(p);
 4461 
 4462         if (fdp->fd_knlist)
 4463                 FREE(fdp->fd_knlist, M_KQUEUE);
 4464         if (fdp->fd_knhash)
 4465                 FREE(fdp->fd_knhash, M_KQUEUE);
 4466 
 4467         FREE_ZONE(fdp, sizeof(*fdp), M_FILEDESC);
 4468 }
 4469 
 4470 
 4471 /*
 4472  * closef_finish
 4473  *
 4474  * Description: Called on last open instance for a fileglob for a file being
 4475  *              closed.
 4476  *
 4477  * Parameters:  fp                      Pointer to fileproc for fd
 4478  *              fg                      Pointer to fileglob for fd
 4479  *              p                       Pointer to proc structure
 4480  *
 4481  * Returns:     0                       Success
 4482  *      <fo_close>:???                  Anything returnable by a per-fileops
 4483  *                                      close function
 4484  *
 4485  * Note:        fp can only be non-NULL if p is also non-NULL.  If p is NULL,
 4486  *              then fg must eith be locked (FHASLOCK) or must not have a
 4487  *              type of DTYPE_VNODE.
 4488  *
 4489  *              On return, the fg is freed.
 4490  *
 4491  *              This function may block draining output to a character
 4492  *              device on last close of that device.
 4493  */
 4494 static int
 4495 closef_finish(struct fileproc *fp, struct fileglob *fg, proc_t p, vfs_context_t ctx)
 4496 {
 4497         int error;
 4498 
 4499 
 4500         /* fg_ops completed initialization? */
 4501         if (fg->fg_ops)
 4502                 error = fo_close(fg, ctx);
 4503         else
 4504                 error = 0;
 4505 
 4506         /* if fp is non-NULL, drain it out */
 4507         if (((fp != (struct fileproc *)0) && ((fp->f_flags & FP_INCHRREAD) != 0))) {
 4508                 proc_fdlock_spin(p);
 4509                 if ( ((fp->f_flags & FP_INCHRREAD) != 0) ) {
 4510                         fileproc_drain(p, fp);
 4511                 }
 4512                 proc_fdunlock(p);
 4513         }
 4514         fg_free(fg);
 4515 
 4516         return (error);
 4517 }
 4518 
 4519 /*
 4520  * closef_locked
 4521  *
 4522  * Description: Internal form of closef; called with proc_fdlock held
 4523  *
 4524  * Parameters:  fp                      Pointer to fileproc for fd
 4525  *              fg                      Pointer to fileglob for fd
 4526  *              p                       Pointer to proc structure
 4527  *
 4528  * Returns:     0                       Success
 4529  *      closef_finish:???               Anything returnable by a per-fileops
 4530  *                                      close function
 4531  *
 4532  * Note:        Decrements reference count on file structure; if this was the
 4533  *              last reference, then closef_finish() is called
 4534  *
 4535  *              p and fp are allowed to  be NULL when closing a file that was
 4536  *              being passed in a message (but only if we are called when this
 4537  *              is NOT the last reference).
 4538  */
 4539 int
 4540 closef_locked(struct fileproc *fp, struct fileglob *fg, proc_t p)
 4541 {
 4542         struct vnode *vp;
 4543         struct flock lf;
 4544         struct vfs_context context;
 4545         int error;
 4546 
 4547         if (fg == NULL) {
 4548                 return (0);
 4549         }
 4550 
 4551         /* Set up context with cred stashed in fg */
 4552         if (p == current_proc())
 4553                 context.vc_thread = current_thread();
 4554         else
 4555                 context.vc_thread = NULL;
 4556         context.vc_ucred = fg->fg_cred;
 4557 
 4558         /*
 4559          * POSIX record locking dictates that any close releases ALL
 4560          * locks owned by this process.  This is handled by setting
 4561          * a flag in the unlock to free ONLY locks obeying POSIX
 4562          * semantics, and not to free BSD-style file locks.
 4563          * If the descriptor was in a message, POSIX-style locks
 4564          * aren't passed with the descriptor.
 4565          */
 4566         if (p && (p->p_ladvflag & P_LADVLOCK) && fg->fg_type == DTYPE_VNODE) {
 4567                 proc_fdunlock(p);
 4568 
 4569                 lf.l_whence = SEEK_SET;
 4570                 lf.l_start = 0;
 4571                 lf.l_len = 0;
 4572                 lf.l_type = F_UNLCK;
 4573                 vp = (struct vnode *)fg->fg_data;
 4574 
 4575                 if ( (error = vnode_getwithref(vp)) == 0 ) {
 4576                         (void) VNOP_ADVLOCK(vp, (caddr_t)p, F_UNLCK, &lf, F_POSIX, &context);
 4577                         (void)vnode_put(vp);
 4578                 }
 4579                 proc_fdlock(p);
 4580         }
 4581         lck_mtx_lock_spin(&fg->fg_lock);
 4582         fg->fg_count--;
 4583 
 4584         if (fg->fg_count > 0) {
 4585                 lck_mtx_unlock(&fg->fg_lock);
 4586                 return (0);
 4587         }
 4588 #if DIAGNOSTIC
 4589         if (fg->fg_count != 0)
 4590                 panic("fg %p: being freed with bad fg_count (%d)", fg, fg->fg_count);
 4591 #endif
 4592 
 4593         if (fp && (fp->f_flags & FP_WRITTEN))
 4594                 fg->fg_flag |= FWASWRITTEN;
 4595 
 4596         fg->fg_lflags |= FG_TERM;
 4597         lck_mtx_unlock(&fg->fg_lock);
 4598 
 4599         if (p)
 4600                 proc_fdunlock(p);
 4601         error = closef_finish(fp, fg, p, &context);
 4602         if (p)
 4603                 proc_fdlock(p);
 4604 
 4605         return(error);
 4606 }
 4607 
 4608 
 4609 /*
 4610  * fileproc_drain
 4611  *
 4612  * Description: Drain out pending I/O operations
 4613  *
 4614  * Parameters:  p                               Process closing this file
 4615  *              fp                              fileproc struct for the open
 4616  *                                              instance on the file
 4617  *
 4618  * Returns:     void
 4619  *
 4620  * Locks:       Assumes the caller holds the proc_fdlock
 4621  *
 4622  * Notes:       For character devices, this occurs on the last close of the
 4623  *              device; for all other file descriptors, this occurs on each
 4624  *              close to prevent fd's from being closed out from under
 4625  *              operations currently in progress and blocked
 4626  *
 4627  * See Also:    file_vnode(), file_socket(), file_drop(), and the cautions
 4628  *              regarding their use and interaction with this function.
 4629  */
 4630 void
 4631 fileproc_drain(proc_t p, struct fileproc * fp)
 4632 {
 4633         struct vfs_context context;
 4634 
 4635         context.vc_thread = proc_thread(p);     /* XXX */
 4636         context.vc_ucred = fp->f_fglob->fg_cred;
 4637 
 4638         fp->f_iocount-- ; /* (the one the close holds) */
 4639 
 4640         while (fp->f_iocount) {
 4641 
 4642                 lck_mtx_convert_spin(&p->p_fdmlock);
 4643 
 4644                 if (fp->f_fglob->fg_ops->fo_drain) {
 4645                         (*fp->f_fglob->fg_ops->fo_drain)(fp, &context);
 4646                 }
 4647                 if ((fp->f_flags & FP_INSELECT) == FP_INSELECT) {
 4648                         if (wait_queue_wakeup_all((wait_queue_t)fp->f_waddr, NULL, THREAD_INTERRUPTED) == KERN_INVALID_ARGUMENT)
 4649                                 panic("bad wait queue for wait_queue_wakeup_all %p", fp->f_waddr);
 4650                 } 
 4651                 if ((fp->f_flags & FP_SELCONFLICT) == FP_SELCONFLICT) {
 4652                         if (wait_queue_wakeup_all(&select_conflict_queue, NULL, THREAD_INTERRUPTED) == KERN_INVALID_ARGUMENT)
 4653                                 panic("bad select_conflict_queue");
 4654                 }
 4655                 p->p_fpdrainwait = 1;
 4656 
 4657                 msleep(&p->p_fpdrainwait, &p->p_fdmlock, PRIBIO, "fpdrain", NULL);
 4658 
 4659         }
 4660 #if DIAGNOSTIC
 4661         if ((fp->f_flags & FP_INSELECT) != 0)
 4662                 panic("FP_INSELECT set on drained fp");
 4663 #endif
 4664         if ((fp->f_flags & FP_SELCONFLICT) == FP_SELCONFLICT)
 4665                 fp->f_flags &= ~FP_SELCONFLICT;
 4666 }
 4667 
 4668 
 4669 /*
 4670  * fp_free
 4671  *
 4672  * Description: Release the fd and free the fileproc associated with the fd
 4673  *              in the per process open file table of the specified process;
 4674  *              these values must correspond.
 4675  *
 4676  * Parameters:  p                               Process containing fd
 4677  *              fd                              fd to be released
 4678  *              fp                              fileproc to be freed
 4679  *
 4680  * Returns:     0                               Success
 4681  *
 4682  * Notes:       XXX function should be void - no one interprets the returns
 4683  *              XXX code
 4684  */
 4685 int
 4686 fp_free(proc_t p, int fd, struct fileproc * fp)
 4687 {
 4688         proc_fdlock_spin(p);
 4689         fdrelse(p, fd);
 4690         proc_fdunlock(p);
 4691 
 4692         fg_free(fp->f_fglob);
 4693         FREE_ZONE(fp, sizeof(*fp), M_FILEPROC);
 4694         return(0);
 4695 }
 4696 
 4697 
 4698 /*
 4699  * flock
 4700  *
 4701  * Description: Apply an advisory lock on a file descriptor.
 4702  *
 4703  * Parameters:  p                               Process making request
 4704  *              uap->fd                         fd on which the lock is to be
 4705  *                                              attempted
 4706  *              uap->how                        (Un)Lock bits, including type
 4707  *              retval                          Pointer to the call return area
 4708  *              
 4709  * Returns:     0                               Success
 4710  *      fp_getfvp:EBADF                         Bad file descriptor
 4711  *      fp_getfvp:ENOTSUP                       fd does not refer to a vnode
 4712  *      vnode_getwithref:???
 4713  *      VNOP_ADVLOCK:???
 4714  *
 4715  * Implicit returns:
 4716  *              *retval (modified)              Size of dtable
 4717  *
 4718  * Notes:       Just attempt to get a record lock of the requested type on
 4719  *              the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
 4720  */
 4721 int
 4722 flock(proc_t p, struct flock_args *uap, __unused int32_t *retval)
 4723 {
 4724         int fd = uap->fd;
 4725         int how = uap->how;
 4726         struct fileproc *fp;
 4727         struct vnode *vp;
 4728         struct flock lf;
 4729         vfs_context_t ctx = vfs_context_current();
 4730         int error=0;
 4731 
 4732         AUDIT_ARG(fd, uap->fd);
 4733         if ( (error = fp_getfvp(p, fd, &fp, &vp)) ) {
 4734                 return(error);
 4735         }
 4736         if ( (error = vnode_getwithref(vp)) ) {
 4737                 goto out1;
 4738         }
 4739         AUDIT_ARG(vnpath, vp, ARG_VNODE1);
 4740 
 4741         lf.l_whence = SEEK_SET;
 4742         lf.l_start = 0;
 4743         lf.l_len = 0;
 4744         if (how & LOCK_UN) {
 4745                 lf.l_type = F_UNLCK;
 4746                 fp->f_flag &= ~FHASLOCK;
 4747                 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_UNLCK, &lf, F_FLOCK, ctx);
 4748                 goto out;
 4749         }
 4750         if (how & LOCK_EX)
 4751                 lf.l_type = F_WRLCK;
 4752         else if (how & LOCK_SH)
 4753                 lf.l_type = F_RDLCK;
 4754         else {
 4755                 error = EBADF;
 4756                 goto out;
 4757         }
 4758 #if CONFIG_MACF
 4759         error = mac_file_check_lock(proc_ucred(p), fp->f_fglob, F_SETLK, &lf);
 4760         if (error)
 4761                 goto out;
 4762 #endif
 4763         fp->f_flag |= FHASLOCK;
 4764         if (how & LOCK_NB) {
 4765                 error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_SETLK, &lf, F_FLOCK, ctx);
 4766                 goto out;       
 4767         }
 4768         error = VNOP_ADVLOCK(vp, (caddr_t)fp->f_fglob, F_SETLK, &lf, F_FLOCK|F_WAIT, ctx);
 4769 out:
 4770         (void)vnode_put(vp);
 4771 out1:
 4772         fp_drop(p, fd, fp, 0);
 4773         return(error);
 4774 
 4775 }
 4776 
 4777 /*
 4778  * fileport_makeport
 4779  *
 4780  * Description: Obtain a Mach send right for a given file descriptor.
 4781  *
 4782  * Parameters:  p               Process calling fileport
 4783  *              uap->fd         The fd to reference
 4784  *              uap->portnamep  User address at which to place port name.
 4785  *
 4786  * Returns:     0               Success.
 4787  *              EBADF           Bad file descriptor.
 4788  *              EINVAL          File descriptor had type that cannot be sent, misc. other errors.
 4789  *              EFAULT          Address at which to store port name is not valid.
 4790  *              EAGAIN          Resource shortage.
 4791  *
 4792  * Implicit returns:
 4793  *              On success, name of send right is stored at user-specified address.             
 4794  */
 4795 int
 4796 fileport_makeport(proc_t p, struct fileport_makeport_args *uap,
 4797     __unused int *retval)
 4798 {
 4799         int err;
 4800         int fd = uap->fd;
 4801         user_addr_t user_portaddr = uap->portnamep;
 4802         struct fileproc *fp = FILEPROC_NULL;
 4803         struct fileglob *fg = NULL;
 4804         ipc_port_t fileport;
 4805         mach_port_name_t name = MACH_PORT_NULL;
 4806 
 4807         err = fp_lookup(p, fd, &fp, 0);
 4808         if (err != 0) {
 4809                 goto out;
 4810         }
 4811 
 4812         if (!filetype_issendable(fp->f_type)) {
 4813                 err = EINVAL;
 4814                 goto out;
 4815         }
 4816 
 4817         /* Dropped when port is deallocated */
 4818         fg = fp->f_fglob;
 4819         fg_ref(fp);
 4820 
 4821         /* Allocate and initialize a port */
 4822         fileport = fileport_alloc(fg);
 4823         if (fileport == IPC_PORT_NULL) {
 4824                 err = EAGAIN;
 4825                 fg_drop(fp);
 4826                 goto out;
 4827         }
 4828         
 4829         /* Add an entry.  Deallocates port on failure. */
 4830         name = ipc_port_copyout_send(fileport, get_task_ipcspace(p->task));
 4831         if (!MACH_PORT_VALID(name)) {
 4832                 err = EINVAL;
 4833                 goto out;
 4834         } 
 4835         
 4836         err = copyout(&name, user_portaddr, sizeof(mach_port_name_t));
 4837         if (err != 0) {
 4838                 goto out;
 4839         }
 4840 
 4841         /* Tag the fileglob for debugging purposes */
 4842         lck_mtx_lock_spin(&fg->fg_lock);
 4843         fg->fg_lflags |= FG_PORTMADE;
 4844         lck_mtx_unlock(&fg->fg_lock);
 4845 
 4846         fp_drop(p, fd, fp, 0);
 4847 
 4848         return 0;
 4849 
 4850 out:
 4851         if (MACH_PORT_VALID(name)) {
 4852                 /* Don't care if another thread races us to deallocate the entry */
 4853                 (void) mach_port_deallocate(get_task_ipcspace(p->task), name);
 4854         }
 4855 
 4856         if (fp != FILEPROC_NULL) {
 4857                 fp_drop(p, fd, fp, 0);
 4858         }
 4859 
 4860         return err;
 4861 }
 4862 
 4863 void
 4864 fileport_releasefg(struct fileglob *fg)
 4865 {
 4866         (void)closef_locked(NULL, fg, PROC_NULL);
 4867 
 4868         return;
 4869 }
 4870 
 4871 
 4872 /*
 4873  * fileport_makefd
 4874  *
 4875  * Description: Obtain the file descriptor for a given Mach send right.
 4876  *
 4877  * Parameters:  p               Process calling fileport
 4878  *              uap->port       Name of send right to file port.
 4879  *
 4880  * Returns:     0               Success
 4881  *              EINVAL          Invalid Mach port name, or port is not for a file.
 4882  *      fdalloc:EMFILE
 4883  *      fdalloc:ENOMEM          Unable to allocate fileproc or extend file table.
 4884  *
 4885  * Implicit returns:
 4886  *              *retval (modified)              The new descriptor
 4887  */
 4888 int
 4889 fileport_makefd(proc_t p, struct fileport_makefd_args *uap, int32_t *retval)
 4890 {
 4891         struct fileglob *fg;
 4892         struct fileproc *fp = FILEPROC_NULL;
 4893         ipc_port_t port = IPC_PORT_NULL;
 4894         mach_port_name_t send = uap->port;
 4895         kern_return_t res;
 4896         int fd;
 4897         int err;
 4898 
 4899         res = ipc_object_copyin(get_task_ipcspace(p->task),
 4900                         send, MACH_MSG_TYPE_COPY_SEND, &port);
 4901 
 4902         if (res != KERN_SUCCESS) {
 4903                 err = EINVAL;
 4904                 goto out;
 4905         }
 4906 
 4907         fg = fileport_port_to_fileglob(port);
 4908         if (fg == NULL) {
 4909                 err = EINVAL;
 4910                 goto out;
 4911         }
 4912 
 4913         MALLOC_ZONE(fp, struct fileproc *, sizeof(*fp), M_FILEPROC, M_WAITOK);
 4914         if (fp == FILEPROC_NULL) {
 4915                 err = ENOMEM;
 4916                 goto out;
 4917         }
 4918 
 4919         bzero(fp, sizeof(*fp));
 4920 
 4921         fp->f_fglob = fg;
 4922         fg_ref(fp);
 4923 
 4924         proc_fdlock(p);
 4925         err = fdalloc(p, 0, &fd);
 4926         if (err != 0) {
 4927                 proc_fdunlock(p);
 4928                 goto out;
 4929         }
 4930         *fdflags(p, fd) |= UF_EXCLOSE;
 4931 
 4932         procfdtbl_releasefd(p, fd, fp);
 4933         proc_fdunlock(p);
 4934 
 4935         *retval = fd;
 4936         err = 0;
 4937 out:
 4938         if ((fp != NULL) && (0 != err)) {
 4939                 FREE_ZONE(fp, sizeof(*fp), M_FILEPROC);
 4940         } 
 4941 
 4942         if (IPC_PORT_NULL != port) {
 4943                 ipc_port_release_send(port);
 4944         }
 4945 
 4946         return err;
 4947 }
 4948 
 4949 
 4950 /*
 4951  * dupfdopen
 4952  *
 4953  * Description: Duplicate the specified descriptor to a free descriptor;
 4954  *              this is the second half of fdopen(), above.
 4955  *
 4956  * Parameters:  fdp                             filedesc pointer to fill in
 4957  *              indx                            fd to dup to
 4958  *              dfd                             fd to dup from
 4959  *              mode                            mode to set on new fd
 4960  *              error                           command code
 4961  *
 4962  * Returns:     0                               Success
 4963  *              EBADF                           Source fd is bad
 4964  *              EACCES                          Requested mode not allowed
 4965  *              !0                              'error', if not ENODEV or
 4966  *                                              ENXIO
 4967  *
 4968  * Notes:       XXX This is not thread safe; see fdopen() above
 4969  */
 4970 int
 4971 dupfdopen(struct filedesc *fdp, int indx, int dfd, int flags, int error)
 4972 {
 4973         struct fileproc *wfp;
 4974         struct fileproc *fp;
 4975 #if CONFIG_MACF
 4976         int myerror;
 4977 #endif
 4978         proc_t p = current_proc();
 4979 
 4980         /*
 4981          * If the to-be-dup'd fd number is greater than the allowed number
 4982          * of file descriptors, or the fd to be dup'd has already been
 4983          * closed, reject.  Note, check for new == old is necessary as
 4984          * falloc could allocate an already closed to-be-dup'd descriptor
 4985          * as the new descriptor.
 4986          */
 4987         proc_fdlock(p);
 4988 
 4989         fp = fdp->fd_ofiles[indx];
 4990         if (dfd < 0 || dfd >= fdp->fd_nfiles ||
 4991                         (wfp = fdp->fd_ofiles[dfd]) == NULL || wfp == fp ||
 4992                         (fdp->fd_ofileflags[dfd] & UF_RESERVED)) {
 4993 
 4994                 proc_fdunlock(p);
 4995                 return (EBADF);
 4996         }
 4997 #if CONFIG_MACF
 4998         myerror = mac_file_check_dup(proc_ucred(p), wfp->f_fglob, dfd);
 4999         if (myerror) {
 5000                 proc_fdunlock(p);
 5001                 return (myerror);
 5002         }
 5003 #endif
 5004         /*
 5005          * There are two cases of interest here.
 5006          *
 5007          * For ENODEV simply dup (dfd) to file descriptor
 5008          * (indx) and return.
 5009          *
 5010          * For ENXIO steal away the file structure from (dfd) and
 5011          * store it in (indx).  (dfd) is effectively closed by
 5012          * this operation.
 5013          *
 5014          * Any other error code is just returned.
 5015          */
 5016         switch (error) {
 5017         case ENODEV:
 5018                 /*
 5019                  * Check that the mode the file is being opened for is a
 5020                  * subset of the mode of the existing descriptor.
 5021                  */
 5022                 if (((flags & (FREAD|FWRITE)) | wfp->f_flag) != wfp->f_flag) {
 5023                         proc_fdunlock(p);
 5024                         return (EACCES);
 5025                 }
 5026                 if (indx > fdp->fd_lastfile)
 5027                         fdp->fd_lastfile = indx;
 5028                 (void)fg_ref(wfp);
 5029 
 5030                 if (fp->f_fglob)
 5031                         fg_free(fp->f_fglob);
 5032                 fp->f_fglob = wfp->f_fglob;
 5033 
 5034                 fdp->fd_ofileflags[indx] = fdp->fd_ofileflags[dfd] |
 5035                         (flags & O_CLOEXEC) ? UF_EXCLOSE : 0;
 5036 
 5037                 proc_fdunlock(p);
 5038                 return (0);
 5039 
 5040         default:
 5041                 proc_fdunlock(p);
 5042                 return (error);
 5043         }
 5044         /* NOTREACHED */
 5045 }
 5046 
 5047 
 5048 /*
 5049  * fg_ref
 5050  *
 5051  * Description: Add a reference to a fileglob by fileproc
 5052  *
 5053  * Parameters:  fp                              fileproc containing fileglob
 5054  *                                              pointer
 5055  *
 5056  * Returns:     void
 5057  *
 5058  * Notes:       XXX Should use OSAddAtomic?
 5059  */
 5060 void
 5061 fg_ref(struct fileproc * fp)
 5062 {
 5063         struct fileglob *fg;
 5064 
 5065         fg = fp->f_fglob;
 5066 
 5067         lck_mtx_lock_spin(&fg->fg_lock);
 5068 
 5069 #if DIAGNOSTIC
 5070         if ((fp->f_flags & ~((unsigned int)FP_VALID_FLAGS)) != 0)
 5071                 panic("fg_ref: invalid bits on fp %p", fp);
 5072 
 5073         if (fg->fg_count == 0)
 5074                 panic("fg_ref: adding fgcount to zeroed fg: fp %p fg %p",
 5075                     fp, fg);
 5076 #endif
 5077         fg->fg_count++;
 5078         lck_mtx_unlock(&fg->fg_lock);
 5079 }
 5080 
 5081 
 5082 /*
 5083  * fg_drop
 5084  *
 5085  * Description: Remove a reference to a fileglob by fileproc
 5086  *
 5087  * Parameters:  fp                              fileproc containing fileglob
 5088  *                                              pointer
 5089  *
 5090  * Returns:     void
 5091  *
 5092  * Notes:       XXX Should use OSAddAtomic?
 5093  */
 5094 void
 5095 fg_drop(struct fileproc * fp)
 5096 {
 5097         struct fileglob *fg;
 5098 
 5099         fg = fp->f_fglob;
 5100         lck_mtx_lock_spin(&fg->fg_lock);
 5101         fg->fg_count--;
 5102         lck_mtx_unlock(&fg->fg_lock);
 5103 }
 5104 
 5105 
 5106 /*
 5107  * fg_insertuipc
 5108  *
 5109  * Description: Insert fileglob onto message queue
 5110  *
 5111  * Parameters:  fg                              Fileglob pointer to insert
 5112  *
 5113  * Returns:     void
 5114  *
 5115  * Locks:       Takes and drops fg_lock, potentially many times
 5116  */
 5117 void
 5118 fg_insertuipc(struct fileglob * fg)
 5119 {
 5120         int insertque = 0;
 5121 
 5122         lck_mtx_lock_spin(&fg->fg_lock);
 5123 
 5124         while (fg->fg_lflags & FG_RMMSGQ) {
 5125                 lck_mtx_convert_spin(&fg->fg_lock);
 5126 
 5127                 fg->fg_lflags |= FG_WRMMSGQ;
 5128                 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_insertuipc", NULL);
 5129         }
 5130 
 5131         fg->fg_count++;
 5132         fg->fg_msgcount++;
 5133         if (fg->fg_msgcount == 1) {
 5134                 fg->fg_lflags |= FG_INSMSGQ;
 5135                 insertque=1;
 5136         }
 5137         lck_mtx_unlock(&fg->fg_lock);
 5138 
 5139         if (insertque) {
 5140                 lck_mtx_lock_spin(uipc_lock);
 5141                 unp_gc_wait();
 5142                 LIST_INSERT_HEAD(&fmsghead, fg, f_msglist);
 5143                 lck_mtx_unlock(uipc_lock);
 5144                 lck_mtx_lock(&fg->fg_lock);
 5145                 fg->fg_lflags &= ~FG_INSMSGQ;
 5146                 if (fg->fg_lflags & FG_WINSMSGQ) {
 5147                         fg->fg_lflags &= ~FG_WINSMSGQ;
 5148                         wakeup(&fg->fg_lflags);
 5149                 }
 5150                 lck_mtx_unlock(&fg->fg_lock);
 5151         }
 5152 
 5153 }
 5154 
 5155 
 5156 /*
 5157  * fg_removeuipc
 5158  *
 5159  * Description: Remove fileglob from message queue
 5160  *
 5161  * Parameters:  fg                              Fileglob pointer to remove
 5162  *
 5163  * Returns:     void
 5164  *
 5165  * Locks:       Takes and drops fg_lock, potentially many times
 5166  */
 5167 void
 5168 fg_removeuipc(struct fileglob * fg)
 5169 {
 5170         int removeque = 0;
 5171 
 5172         lck_mtx_lock_spin(&fg->fg_lock);
 5173         while (fg->fg_lflags & FG_INSMSGQ) {
 5174                 lck_mtx_convert_spin(&fg->fg_lock);
 5175 
 5176                 fg->fg_lflags |= FG_WINSMSGQ;
 5177                 msleep(&fg->fg_lflags, &fg->fg_lock, 0, "fg_removeuipc", NULL);
 5178         }
 5179         fg->fg_msgcount--;
 5180         if (fg->fg_msgcount == 0) {
 5181                 fg->fg_lflags |= FG_RMMSGQ;
 5182                 removeque=1;
 5183         }
 5184         lck_mtx_unlock(&fg->fg_lock);
 5185 
 5186         if (removeque) {
 5187                 lck_mtx_lock_spin(uipc_lock);
 5188                 unp_gc_wait();
 5189                 LIST_REMOVE(fg, f_msglist);
 5190                 lck_mtx_unlock(uipc_lock);
 5191                 lck_mtx_lock(&fg->fg_lock);
 5192                 fg->fg_lflags &= ~FG_RMMSGQ;
 5193                 if (fg->fg_lflags & FG_WRMMSGQ) {
 5194                         fg->fg_lflags &= ~FG_WRMMSGQ;
 5195                         wakeup(&fg->fg_lflags);
 5196                 }
 5197                 lck_mtx_unlock(&fg->fg_lock);
 5198         }
 5199 }
 5200 
 5201 
 5202 /*
 5203  * fo_read
 5204  *
 5205  * Description: Generic fileops read indirected through the fileops pointer
 5206  *              in the fileproc structure
 5207  *
 5208  * Parameters:  fp                              fileproc structure pointer
 5209  *              uio                             user I/O structure pointer
 5210  *              flags                           FOF_ flags
 5211  *              ctx                             VFS context for operation
 5212  *
 5213  * Returns:     0                               Success
 5214  *              !0                              Errno from read
 5215  */
 5216 int
 5217 fo_read(struct fileproc *fp, struct uio *uio, int flags, vfs_context_t ctx)
 5218 {
 5219         return ((*fp->f_ops->fo_read)(fp, uio, flags, ctx));
 5220 }
 5221 
 5222 
 5223 /*
 5224  * fo_write
 5225  *
 5226  * Description: Generic fileops write indirected through the fileops pointer
 5227  *              in the fileproc structure
 5228  *
 5229  * Parameters:  fp                              fileproc structure pointer
 5230  *              uio                             user I/O structure pointer
 5231  *              flags                           FOF_ flags
 5232  *              ctx                             VFS context for operation
 5233  *
 5234  * Returns:     0                               Success
 5235  *              !0                              Errno from write
 5236  */
 5237 int
 5238 fo_write(struct fileproc *fp, struct uio *uio, int flags, vfs_context_t ctx)
 5239 {
 5240         return((*fp->f_ops->fo_write)(fp, uio, flags, ctx));
 5241 }
 5242 
 5243 
 5244 /*
 5245  * fo_ioctl
 5246  *
 5247  * Description: Generic fileops ioctl indirected through the fileops pointer
 5248  *              in the fileproc structure
 5249  *
 5250  * Parameters:  fp                              fileproc structure pointer
 5251  *              com                             ioctl command
 5252  *              data                            pointer to internalized copy
 5253  *                                              of user space ioctl command
 5254  *                                              parameter data in kernel space
 5255  *              ctx                             VFS context for operation
 5256  *
 5257  * Returns:     0                               Success
 5258  *              !0                              Errno from ioctl
 5259  *
 5260  * Locks:       The caller is assumed to have held the proc_fdlock; this
 5261  *              function releases and reacquires this lock.  If the caller
 5262  *              accesses data protected by this lock prior to calling this
 5263  *              function, it will need to revalidate/reacquire any cached
 5264  *              protected data obtained prior to the call.
 5265  */
 5266 int 
 5267 fo_ioctl(struct fileproc *fp, u_long com, caddr_t data, vfs_context_t ctx)
 5268 {
 5269         int error;
 5270 
 5271         proc_fdunlock(vfs_context_proc(ctx));
 5272         error = (*fp->f_ops->fo_ioctl)(fp, com, data, ctx);
 5273         proc_fdlock(vfs_context_proc(ctx));
 5274         return(error);
 5275 }       
 5276 
 5277 
 5278 /*
 5279  * fo_select
 5280  *
 5281  * Description: Generic fileops select indirected through the fileops pointer
 5282  *              in the fileproc structure
 5283  *
 5284  * Parameters:  fp                              fileproc structure pointer
 5285  *              which                           select which
 5286  *              wql                             pointer to wait queue list
 5287  *              ctx                             VFS context for operation
 5288  *
 5289  * Returns:     0                               Success
 5290  *              !0                              Errno from select
 5291  */
 5292 int
 5293 fo_select(struct fileproc *fp, int which, void *wql, vfs_context_t ctx)
 5294 {       
 5295         return((*fp->f_ops->fo_select)(fp, which, wql, ctx));
 5296 }
 5297 
 5298 
 5299 /*
 5300  * fo_close
 5301  *
 5302  * Description: Generic fileops close indirected through the fileops pointer
 5303  *              in the fileproc structure
 5304  *
 5305  * Parameters:  fp                              fileproc structure pointer for
 5306  *                                              file to close
 5307  *              ctx                             VFS context for operation
 5308  *
 5309  * Returns:     0                               Success
 5310  *              !0                              Errno from close
 5311  */
 5312 int
 5313 fo_close(struct fileglob *fg, vfs_context_t ctx)
 5314 {       
 5315         return((*fg->fg_ops->fo_close)(fg, ctx));
 5316 }
 5317 
 5318 
 5319 /*
 5320  * fo_kqfilter
 5321  *
 5322  * Description: Generic fileops kqueue filter indirected through the fileops
 5323  *              pointer in the fileproc structure
 5324  *
 5325  * Parameters:  fp                              fileproc structure pointer
 5326  *              kn                              pointer to knote to filter on
 5327  *              ctx                             VFS context for operation
 5328  *
 5329  * Returns:     0                               Success
 5330  *              !0                              Errno from kqueue filter
 5331  */
 5332 int
 5333 fo_kqfilter(struct fileproc *fp, struct knote *kn, vfs_context_t ctx)
 5334 {
 5335         return ((*fp->f_ops->fo_kqfilter)(fp, kn, ctx));
 5336 }
 5337 
 5338 /*
 5339  * The ability to send a file descriptor to another
 5340  * process is opt-in by file type.
 5341  */
 5342 boolean_t
 5343 filetype_issendable(file_type_t fdtype) 
 5344 {
 5345         switch (fdtype) {
 5346                 case DTYPE_VNODE:
 5347                 case DTYPE_SOCKET:
 5348                 case DTYPE_PIPE:
 5349                 case DTYPE_PSXSHM:
 5350                         return TRUE;
 5351                 default:
 5352                         /* DTYPE_KQUEUE, DTYPE_FSEVENTS, DTYPE_PSXSEM */
 5353                         return FALSE;
 5354         }
 5355 }

Cache object: e9780337926472f1e3a3041225c03eca


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.