]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_descrip.c
xnu-1456.1.26.tar.gz
[apple/xnu.git] / bsd / kern / kern_descrip.c
index f7bd0e5d9c524bd4add64ec3e226eaf92527a57e..ddf2bb279c5a58f4a5b4acaedf8fa7c1049ceb5a 100644 (file)
@@ -93,8 +93,9 @@
 #include <sys/aio_kern.h>
 #include <sys/ev.h>
 #include <kern/lock.h>
+#include <sys/uio_internal.h>
 
-#include <bsm/audit_kernel.h>
+#include <security/audit/audit.h>
 
 #include <sys/mount_internal.h>
 #include <sys/kdebug.h>
 
 #include <sys/ubc_internal.h>
 
-#include <hfs/hfs.h>   /* <rdar://7042269 manifest constants */
-
 struct psemnode;
 struct pshmnode;
 
 int fdopen(dev_t dev, int mode, int type, proc_t p);
-int finishdup(proc_t p, struct filedesc *fdp, int old, int new, register_t *retval);
+int finishdup(proc_t p, struct filedesc *fdp, int old, int new, int32_t *retval);
 
 int falloc_locked(proc_t p, struct fileproc **resultfp, int *resultfd, vfs_context_t ctx, int locked);
-int fdgetf_noref(proc_t p, int fd, struct fileproc **resultfp);
 void fg_drop(struct fileproc * fp);
 void fg_free(struct fileglob *fg);
 void fg_ref(struct fileproc * fp);
@@ -128,7 +126,7 @@ static int closef_finish(struct fileproc *fp, struct fileglob *fg, proc_t p, vfs
 
 /* We don't want these exported */
 __private_extern__
-int open1(vfs_context_t, struct nameidata *, int, struct vnode_attr *, register_t *);
+int open1(vfs_context_t, struct nameidata *, int, struct vnode_attr *, int32_t *);
 
 __private_extern__
 int unlink1(vfs_context_t, struct nameidata *, int);
@@ -264,7 +262,7 @@ proc_fdunlock(proc_t p)
  *             *retval (modified)              Size of dtable
  */
 int
-getdtablesize(proc_t p, __unused struct getdtablesize_args *uap, register_t *retval)
+getdtablesize(proc_t p, __unused struct getdtablesize_args *uap, int32_t *retval)
 {
        proc_fdlock_spin(p);
        *retval = min((int)p->p_rlimit[RLIMIT_NOFILE].rlim_cur, maxfiles);
@@ -355,6 +353,82 @@ _fdrelse(struct proc * p, int fd)
 }
 
 
+int
+fd_rdwr(
+       int fd,
+       enum uio_rw rw,
+       uint64_t base,
+       int64_t len,
+       enum uio_seg segflg,
+       off_t   offset,
+       int     io_flg,
+       int64_t *aresid)
+{
+        struct fileproc *fp;
+       proc_t  p;
+        int error = 0;
+       int flags = 0;
+       int spacetype;
+       uio_t auio = NULL;
+       char uio_buf[ UIO_SIZEOF(1) ];
+       struct vfs_context context = *(vfs_context_current());
+
+       p = current_proc();
+
+        error = fp_lookup(p, fd, &fp, 0);
+        if (error)
+                return(error);
+
+       if (fp->f_type != DTYPE_VNODE && fp->f_type != DTYPE_PIPE && fp->f_type != DTYPE_SOCKET) {
+               error = EINVAL;
+               goto out;
+       }
+       if (rw == UIO_WRITE && !(fp->f_flag & FWRITE)) {
+                error = EBADF;
+               goto out;
+       }
+       
+       if (rw == UIO_READ && !(fp->f_flag & FREAD)) {
+               error = EBADF;
+               goto out;
+       }
+       
+       context.vc_ucred = fp->f_fglob->fg_cred;
+
+       if (UIO_SEG_IS_USER_SPACE(segflg))
+               spacetype = proc_is64bit(p) ? UIO_USERSPACE64 : UIO_USERSPACE32;
+       else
+               spacetype = UIO_SYSSPACE;
+
+       auio = uio_createwithbuffer(1, offset, spacetype, rw, &uio_buf[0], sizeof(uio_buf));
+
+       uio_addiov(auio, base, len);
+
+       if ( !(io_flg & IO_APPEND))
+               flags = FOF_OFFSET;
+
+       if (rw == UIO_WRITE)
+               error = fo_write(fp, auio, flags, &context);
+       else
+               error = fo_read(fp, auio, flags, &context);
+
+       if (aresid)
+               *aresid = uio_resid(auio);
+       else {
+               if (uio_resid(auio) && error == 0)
+                       error = EIO;
+       }
+out:
+        if (rw == UIO_WRITE && error == 0)
+                fp_drop_written(p, fd, fp);
+        else
+                fp_drop(p, fd, fp, 0);
+
+       return error;
+}
+
+
+
 /*
  * dup
  *
@@ -371,7 +445,7 @@ _fdrelse(struct proc * p, int fd)
  *             *retval (modified)              The new descriptor
  */
 int
-dup(proc_t p, struct dup_args *uap, register_t *retval)
+dup(proc_t p, struct dup_args *uap, int32_t *retval)
 {
        struct filedesc *fdp = p->p_fd;
        int old = uap->fd;
@@ -413,7 +487,7 @@ dup(proc_t p, struct dup_args *uap, register_t *retval)
  *             *retval (modified)              The new descriptor
  */
 int
-dup2(proc_t p, struct dup2_args *uap, register_t *retval)
+dup2(proc_t p, struct dup2_args *uap, int32_t *retval)
 {
        struct filedesc *fdp = p->p_fd;
        int old = uap->from, new = uap->to;
@@ -518,7 +592,7 @@ closeit:
  *             blocking operation.
  */
 int
-fcntl(proc_t p, struct fcntl_args *uap, register_t *retval)
+fcntl(proc_t p, struct fcntl_args *uap, int32_t *retval)
 {
        __pthread_testcancel(1);
        return(fcntl_nocancel(p, (struct fcntl_nocancel_args *)uap, retval));
@@ -579,7 +653,7 @@ fcntl(proc_t p, struct fcntl_args *uap, register_t *retval)
  *             *retval (modified)              fcntl return value (if any)
  */
 int
-fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
+fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, int32_t *retval)
 {
        int fd = uap->fd;
        struct filedesc *fdp = p->p_fd;
@@ -622,7 +696,7 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                 * from a 32-bit process we lop off the top 32-bits to avoid
                 * getting the wrong address
                 */
-               argp = CAST_USER_ADDR_T(uap->arg);
+               argp = CAST_USER_ADDR_T((uint32_t)uap->arg);
        }
 
        pop = &fdp->fd_ofileflags[fd];
@@ -637,7 +711,8 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
        switch (uap->cmd) {
 
        case F_DUPFD:
-               newmin = CAST_DOWN(int, uap->arg);
+               newmin = CAST_DOWN_EXPLICIT(int, uap->arg); /* arg is an int, so we won't lose bits */
+               AUDIT_ARG(value32, newmin);
                if ((u_int)newmin >= p->p_rlimit[RLIMIT_NOFILE].rlim_cur ||
                    newmin >= maxfiles) {
                        error = EINVAL;
@@ -654,6 +729,7 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                goto out;
 
        case F_SETFD:
+               AUDIT_ARG(value32, uap->arg);
                *pop = (*pop &~ UF_EXCLOSE) |
                        (uap->arg & 1)? UF_EXCLOSE : 0;
                error = 0;
@@ -666,7 +742,8 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
 
        case F_SETFL:
                fp->f_flag &= ~FCNTLFLAGS;
-               tmp = CAST_DOWN(int, uap->arg);
+               tmp = CAST_DOWN_EXPLICIT(int, uap->arg); /* arg is an int, so we won't lose bits */
+               AUDIT_ARG(value32, tmp);
                fp->f_flag |= FFLAGS(tmp) & FCNTLFLAGS;
                tmp = fp->f_flag & FNONBLOCK;
                error = fo_ioctl(fp, FIONBIO, (caddr_t)&tmp, &context);
@@ -692,7 +769,8 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                goto out;
 
        case F_SETOWN:
-               tmp = CAST_DOWN(pid_t, uap->arg);
+               tmp = CAST_DOWN_EXPLICIT(pid_t, uap->arg); /* arg is an int, so we won't lose bits */
+               AUDIT_ARG(value32, tmp);
                if (fp->f_type == DTYPE_SOCKET) {
                        ((struct socket *)fp->f_data)->so_pgid = tmp;
                        error =0;
@@ -766,7 +844,7 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                                goto outdrop;
                        }
                        // XXX UInt32 unsafe for LP64 kernel
-                       OSBitOrAtomic(P_LADVLOCK, (UInt32 *)&p->p_ladvflag);
+                       OSBitOrAtomic(P_LADVLOCK, &p->p_ladvflag);
                        error = VNOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg, &context);
                        (void)vnode_put(vp);
                        goto outdrop;
@@ -778,7 +856,7 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                                goto outdrop;
                        }
                        // XXX UInt32 unsafe for LP64 kernel
-                       OSBitOrAtomic(P_LADVLOCK, (UInt32 *)&p->p_ladvflag);
+                       OSBitOrAtomic(P_LADVLOCK, &p->p_ladvflag);
                        error = VNOP_ADVLOCK(vp, (caddr_t)p, F_SETLK, &fl, flg, &context);
                        (void)vnode_put(vp);
                        goto outdrop;
@@ -962,6 +1040,7 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                error = copyin(argp, (caddr_t)&offset, sizeof (off_t));
                if (error)
                        goto outdrop;
+               AUDIT_ARG(value64, offset);
 
                error = vnode_getwithref(vp);
                if (error)
@@ -1081,7 +1160,7 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
 
        case F_READBOOTSTRAP:
        case F_WRITEBOOTSTRAP: {
-               fbootstraptransfer_t fbt_struct;
+               user32_fbootstraptransfer_t user32_fbt_struct;
                user_fbootstraptransfer_t user_fbt_struct;
                int     sizeof_struct;
                caddr_t boot_structp;
@@ -1098,8 +1177,8 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                        boot_structp = (caddr_t) &user_fbt_struct;
                }
                else {
-                       sizeof_struct = sizeof(fbt_struct);
-                       boot_structp = (caddr_t) &fbt_struct;
+                       sizeof_struct = sizeof(user32_fbt_struct);
+                       boot_structp = (caddr_t) &user32_fbt_struct;
                }
                error = copyin(argp, boot_structp, sizeof_struct);
                if (error)
@@ -1211,6 +1290,7 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
 
                if ( (error = copyinstr(argp, pathbufp, MAXPATHLEN, &pathlen)) == 0 ) {
                        if ( (error = vnode_getwithref(vp)) == 0 ) {
+                               AUDIT_ARG(text, pathbufp);
                                error = vn_path_package_check(vp, pathbufp, pathlen, retval);
 
                                (void)vnode_put(vp);
@@ -1273,7 +1353,7 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                if (IS_64BIT_PROCESS(p)) {
                        error = copyin(argp, &fopen, sizeof(fopen));
                } else {
-                       struct fopenfrom fopen32;
+                       struct user32_fopenfrom fopen32;
 
                        error = copyin(argp, &fopen32, sizeof(fopen32));
                        fopen.o_flags = fopen32.o_flags;
@@ -1284,6 +1364,8 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                        vnode_put(vp);
                        goto outdrop;
                }
+               AUDIT_ARG(fflags, fopen.o_flags);
+               AUDIT_ARG(mode, fopen.o_mode);
                VATTR_INIT(&va);
                /* Mask off all but regular access permissions */
                cmode = ((fopen.o_mode &~ fdp->fd_cmask) & ALLPERMS) & ~S_ISTXT;
@@ -1345,10 +1427,12 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
 
        }
 
-       case F_ADDSIGS: {
+       case F_ADDSIGS:
+       case F_ADDFILESIGS:
+       {
                struct user_fsignatures fs;
                kern_return_t kr;
-               vm_address_t kernel_blob_addr;
+               vm_offset_t kernel_blob_addr;
                vm_size_t kernel_blob_size;
 
                if (fp->f_type != DTYPE_VNODE) {
@@ -1364,7 +1448,7 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                if (IS_64BIT_PROCESS(p)) {
                        error = copyin(argp, &fs, sizeof (fs));
                } else {
-                       struct fsignatures fs32;
+                       struct user32_fsignatures fs32;
 
                        error = copyin(argp, &fs32, sizeof (fs32));
                        fs.fs_file_start = fs32.fs_file_start;
@@ -1379,8 +1463,10 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
 
                if(ubc_cs_blob_get(vp, CPU_TYPE_ANY, fs.fs_file_start))
                {
+                       /*
                        if(cs_debug)
                                printf("CODE SIGNING: resident blob offered for: %s\n", vp->v_name);
+                        */
                        vnode_put(vp);
                        goto outdrop;
                }
@@ -1400,9 +1486,23 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                        goto outdrop;
                }
 
-               error = copyin(fs.fs_blob_start,
-                              (void *) kernel_blob_addr,
-                              kernel_blob_size);
+               if(uap->cmd == F_ADDSIGS) {
+                       error = copyin(fs.fs_blob_start,
+                                      (void *) kernel_blob_addr,
+                                      kernel_blob_size);
+               } else /* F_ADDFILESIGS */ {
+                       error = vn_rdwr(UIO_READ,
+                                       vp,
+                                       (caddr_t) kernel_blob_addr,
+                                       kernel_blob_size,
+                                        fs.fs_file_start + fs.fs_blob_start,
+                                       UIO_SYSSPACE,
+                                       0,
+                                       kauth_cred_get(),
+                                       0,
+                                       p);
+               }
+               
                if (error) {
                        ubc_cs_blob_deallocate(kernel_blob_addr,
                                               kernel_blob_size);
@@ -1510,8 +1610,6 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                        char stkbuf[STK_PARAMS];
                        unsigned int size;
                        caddr_t data, memp;
-                       int fix_cmd = uap->cmd;
-
                        /*
                         * For this to work properly, we have to copy in the
                         * ioctl() cmd argument if there is one; we must also
@@ -1529,32 +1627,19 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                                break;
                        }
 
-                       /*
-                        * <rdar://7042269> fix up the command we should have
-                        * received via fcntl with one with a valid size and
-                        * copy out argument.
-                        */
-                       if (fix_cmd == HFS_GET_MOUNT_TIME ||
-                           fix_cmd == HFS_GET_LAST_MTIME) {
-                               if (is64bit)
-                                       size = sizeof(user_time_t);
-                               else
-                                       size = sizeof(time_t);
-                               fix_cmd |= IOC_OUT;
-                       }
-
                        memp = NULL;
                        if (size > sizeof (stkbuf)) {
                                if ((memp = (caddr_t)kalloc(size)) == 0) {
                                        (void)vnode_put(vp);
                                        error = ENOMEM;
+                                       goto outdrop;
                                }
                                data = memp;
                        } else {
                                data = &stkbuf[0];
                        }
                        
-                       if (fix_cmd & IOC_IN) {
+                       if (uap->cmd & IOC_IN) {
                                if (size) {
                                        /* structure */
                                        error = copyin(argp, data, size);
@@ -1572,13 +1657,13 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                                                *(uint32_t *)data = (uint32_t)argp;
                                        }
                                };
-                       } else if ((fix_cmd & IOC_OUT) && size) {
+                       } else if ((uap->cmd & IOC_OUT) && size) {
                                /*
                                 * Zero the buffer so the user always
                                 * gets back something deterministic.
                                 */
                                bzero(data, size);
-                       } else if (fix_cmd & IOC_VOID) {
+                       } else if (uap->cmd & IOC_VOID) {
                                if (is64bit) {
                                    *(user_addr_t *)data = argp;
                                } else {
@@ -1586,18 +1671,12 @@ fcntl_nocancel(proc_t p, struct fcntl_nocancel_args *uap, register_t *retval)
                                }
                        }
 
-                       /*
-                        * <rdar://7042269> We pass the unmodified uap->cmd
-                        * to the underlying VNOP so that we don't confuse it;
-                        * but we are going to handle its copyout() when it
-                        * gets back.
-                        */
                        error = VNOP_IOCTL(vp, uap->cmd, CAST_DOWN(caddr_t, data), 0, &context);
 
                        (void)vnode_put(vp);
 
                        /* Copy any output data to user */
-                       if (error == 0 && (fix_cmd & IOC_OUT) && size) 
+                       if (error == 0 && (uap->cmd & IOC_OUT) && size) 
                                error = copyout(data, argp, size);
                        if (memp)
                                kfree(memp, size);
@@ -1641,7 +1720,7 @@ out:
  *             has not been subsequently changes out from under it.
  */
 int
-finishdup(proc_t p, struct filedesc *fdp, int old, int new, register_t *retval)
+finishdup(proc_t p, struct filedesc *fdp, int old, int new, int32_t *retval)
 {
        struct fileproc *nfp;
        struct fileproc *ofp;
@@ -1720,7 +1799,7 @@ finishdup(proc_t p, struct filedesc *fdp, int old, int new, register_t *retval)
  *                                     close function
  */
 int
-close(proc_t p, struct close_args *uap, register_t *retval)
+close(proc_t p, struct close_args *uap, int32_t *retval)
 {
        __pthread_testcancel(1);
        return(close_nocancel(p, (struct close_nocancel_args *)uap, retval));
@@ -1728,7 +1807,7 @@ close(proc_t p, struct close_args *uap, register_t *retval)
 
 
 int
-close_nocancel(proc_t p, struct close_nocancel_args *uap, __unused register_t *retval)
+close_nocancel(proc_t p, struct close_nocancel_args *uap, __unused int32_t *retval)
 {
        struct fileproc *fp;
        int fd = uap->fd;
@@ -1901,10 +1980,16 @@ static int
 fstat1(proc_t p, int fd, user_addr_t ub, user_addr_t xsecurity, user_addr_t xsecurity_size, int isstat64)
 {
        struct fileproc *fp;
-       struct stat sb;
-       struct stat64 sb64;
-       struct user_stat user_sb;
-       struct user_stat64 user_sb64;
+       union {
+               struct stat sb;
+               struct stat64 sb64;
+       } source;
+       union {
+               struct user64_stat user64_sb;
+               struct user32_stat user32_sb;
+               struct user64_stat64 user64_sb64;
+               struct user32_stat64 user32_sb64;
+       } dest;
        int error, my_size;
        int funnel_state;
        file_type_t type;
@@ -1924,7 +2009,7 @@ fstat1(proc_t p, int fd, user_addr_t ub, user_addr_t xsecurity, user_addr_t xsec
        data = fp->f_data;
        fsec = KAUTH_FILESEC_NONE;
 
-       sbptr = (isstat64 != 0) ? (void *)&sb64: (void *)&sb;
+       sbptr = (void *)&source;
 
        switch (type) {
 
@@ -1974,28 +2059,31 @@ fstat1(proc_t p, int fd, user_addr_t ub, user_addr_t xsecurity, user_addr_t xsec
                caddr_t sbp;
 
                if (isstat64 != 0) {
-                       sb64.st_lspare = 0;
-                       sb64.st_qspare[0] = 0LL;
-                       sb64.st_qspare[1] = 0LL;
+                       source.sb64.st_lspare = 0;
+                       source.sb64.st_qspare[0] = 0LL;
+                       source.sb64.st_qspare[1] = 0LL;
+
                        if (IS_64BIT_PROCESS(current_proc())) {
-                               munge_stat64(&sb64, &user_sb64); 
-                               my_size = sizeof(user_sb64);
-                               sbp = (caddr_t)&user_sb64;
+                               munge_user64_stat64(&source.sb64, &dest.user64_sb64); 
+                               my_size = sizeof(dest.user64_sb64);
+                               sbp = (caddr_t)&dest.user64_sb64;
                        } else {
-                               my_size = sizeof(sb64);
-                               sbp = (caddr_t)&sb64;
+                               munge_user32_stat64(&source.sb64, &dest.user32_sb64); 
+                               my_size = sizeof(dest.user32_sb64);
+                               sbp = (caddr_t)&dest.user32_sb64;
                        }
                } else {
-                       sb.st_lspare = 0;
-                       sb.st_qspare[0] = 0LL;
-                       sb.st_qspare[1] = 0LL;
+                       source.sb.st_lspare = 0;
+                       source.sb.st_qspare[0] = 0LL;
+                       source.sb.st_qspare[1] = 0LL;
                        if (IS_64BIT_PROCESS(current_proc())) {
-                               munge_stat(&sb, &user_sb); 
-                               my_size = sizeof(user_sb);
-                               sbp = (caddr_t)&user_sb;
+                               munge_user64_stat(&source.sb, &dest.user64_sb); 
+                               my_size = sizeof(dest.user64_sb);
+                               sbp = (caddr_t)&dest.user64_sb;
                        } else {
-                               my_size = sizeof(sb);
-                               sbp = (caddr_t)&sb;
+                               munge_user32_stat(&source.sb, &dest.user32_sb); 
+                               my_size = sizeof(dest.user32_sb);
+                               sbp = (caddr_t)&dest.user32_sb;
                        }
                }
 
@@ -2051,7 +2139,7 @@ out:
  *             !0                              Errno (see fstat1)
  */
 int
-fstat_extended(proc_t p, struct fstat_extended_args *uap, __unused register_t *retval)
+fstat_extended(proc_t p, struct fstat_extended_args *uap, __unused int32_t *retval)
 {
        return(fstat1(p, uap->fd, uap->ub, uap->xsecurity, uap->xsecurity_size, 0));
 }
@@ -2070,7 +2158,7 @@ fstat_extended(proc_t p, struct fstat_extended_args *uap, __unused register_t *r
  *             !0                              Errno (see fstat1)
  */
 int
-fstat(proc_t p, register struct fstat_args *uap, __unused register_t *retval)
+fstat(proc_t p, register struct fstat_args *uap, __unused int32_t *retval)
 {
        return(fstat1(p, uap->fd, uap->ub, 0, 0, 0));
 }
@@ -2093,7 +2181,7 @@ fstat(proc_t p, register struct fstat_args *uap, __unused register_t *retval)
  *             !0                              Errno (see fstat1)
  */
 int
-fstat64_extended(proc_t p, struct fstat64_extended_args *uap, __unused register_t *retval)
+fstat64_extended(proc_t p, struct fstat64_extended_args *uap, __unused int32_t *retval)
 {
        return(fstat1(p, uap->fd, uap->ub, uap->xsecurity, uap->xsecurity_size, 1));
 }
@@ -2113,7 +2201,7 @@ fstat64_extended(proc_t p, struct fstat64_extended_args *uap, __unused register_
  *             !0                              Errno (see fstat1)
  */
 int
-fstat64(proc_t p, register struct fstat64_args *uap, __unused register_t *retval)
+fstat64(proc_t p, register struct fstat64_args *uap, __unused int32_t *retval)
 {
        return(fstat1(p, uap->fd, uap->ub, 0, 0, 1));
 }
@@ -2139,7 +2227,7 @@ fstat64(proc_t p, register struct fstat64_args *uap, __unused register_t *retval
  *             *retval (modified)              Returned information (numeric)
  */
 int
-fpathconf(proc_t p, struct fpathconf_args *uap, register_t *retval)
+fpathconf(proc_t p, struct fpathconf_args *uap, int32_t *retval)
 {
        int fd = uap->fd;
        struct fileproc *fp;
@@ -2158,8 +2246,8 @@ fpathconf(proc_t p, struct fpathconf_args *uap, register_t *retval)
        switch (type) {
 
        case DTYPE_SOCKET:
-               if (uap->name != _PC_PIPE_BUF) {
-                       error = EINVAL;
+               if (uap->name != _PC_PIPE_BUF) {
+                       error = EINVAL;
                        goto out;
                }
                *retval = PIPE_BUF;
@@ -2167,7 +2255,11 @@ fpathconf(proc_t p, struct fpathconf_args *uap, register_t *retval)
                goto out;
 
        case DTYPE_PIPE:
-               *retval = PIPE_BUF;
+               if (uap->name != _PC_PIPE_BUF) {
+                       error = EINVAL;
+                       goto out;
+               }
+               *retval = PIPE_BUF;
                error = 0;
                goto out;
 
@@ -2806,7 +2898,7 @@ fp_getfpipe(proc_t p, int fd, struct fileproc **resultfp,
        return (0);
 }
 
-
+#if NETAT
 #define DTYPE_ATALK -1         /* XXX This does not belong here */
 
 
@@ -2866,6 +2958,7 @@ fp_getfatalk(proc_t p, int fd, struct fileproc **resultfp,
        return (0);
 }
 
+#endif /* NETAT */
 
 /*
  * fp_lookup
@@ -3095,7 +3188,75 @@ file_vnode(int fd, struct vnode **vpp)
                proc_fdunlock(p);
                return(EINVAL);
        }
-       *vpp = (struct vnode *)fp->f_data;
+       if (vpp != NULL)
+               *vpp = (struct vnode *)fp->f_data;
+       proc_fdunlock(p);
+
+       return(0);
+}
+
+
+/*
+ * file_vnode_withvid
+ *
+ * Description:        Given an fd, look it up in the current process's per process
+ *             open file table, and return its internal vnode pointer.
+ *
+ * Parameters: fd                              fd to obtain vnode from
+ *             vpp                             pointer to vnode return area
+ *             vidp                            pointer to vid of the returned vnode
+ *
+ * Returns:    0                               Success
+ *             EINVAL                          The fd does not refer to a
+ *                                             vnode fileproc entry
+ *     fp_lookup:EBADF                         Bad file descriptor
+ *
+ * Implicit returns:
+ *             *vpp (modified)                 Returned vnode pointer
+ *
+ * Locks:      This function internally takes and drops the proc_fdlock for
+ *             the current process
+ *
+ * Notes:      If successful, this function increments the f_iocount on the
+ *             fd's corresponding fileproc.
+ *
+ *             The fileproc referenced is not returned; because of this, care
+ *             must be taken to not drop the last reference (e.g. by closing
+ *             the file).  This is inhernely unsafe, since the reference may
+ *             not be recoverable from the vnode, if there is a subsequent
+ *             close that destroys the associate fileproc.  The caller should
+ *             therefore retain their own reference on the fileproc so that
+ *             the f_iocount can be dropped subsequently.  Failure to do this
+ *             can result in the returned pointer immediately becoming invalid
+ *             following the call.
+ *
+ *             Use of this function is discouraged.
+ */
+int
+file_vnode_withvid(int fd, struct vnode **vpp, uint32_t * vidp)
+{
+       proc_t p = current_proc();
+       struct fileproc *fp;
+       vnode_t vp;
+       int error;
+       
+       proc_fdlock_spin(p);
+       if ( (error = fp_lookup(p, fd, &fp, 1)) ) {
+               proc_fdunlock(p);
+               return(error);
+       }
+       if (fp->f_type != DTYPE_VNODE) {
+               fp_drop(p, fd, fp,1);
+               proc_fdunlock(p);
+               return(EINVAL);
+       }
+       vp = (struct vnode *)fp->f_data;
+       if (vpp != NULL) 
+               *vpp = vp;
+
+       if ((vidp != NULL) && (vp != NULLVP)) 
+               *vidp = (uint32_t)vp->v_id;
+
        proc_fdunlock(p);
 
        return(0);
@@ -3515,10 +3676,12 @@ void
 fdexec(proc_t p)
 {
        struct filedesc *fdp = p->p_fd;
-       int i = fdp->fd_lastfile;
+       int i;
        struct fileproc *fp;
 
        proc_fdlock(p);
+       i = fdp->fd_lastfile;
+
        while (i >= 0) {
 
                fp = fdp->fd_ofiles[i];
@@ -3718,6 +3881,7 @@ fdcopy(proc_t p, vnode_t uth_cdir)
                        for (i = newfdp->fd_lastfile; i >= 0; i--, fpp--) {
                                if (*fpp != NULL && (*fpp)->f_type == DTYPE_KQUEUE) {
                                        *fpp = NULL;
+                                       newfdp->fd_ofileflags[i] = 0;
                                        if (i < newfdp->fd_freefile)
                                                newfdp->fd_freefile = i;
                                }
@@ -3974,7 +4138,6 @@ closef_locked(struct fileproc *fp, struct fileglob *fg, proc_t p)
        if (p)
                proc_fdunlock(p);
        error = closef_finish(fp, fg, p, &context);
-
        if (p)
                proc_fdlock(p);
 
@@ -3982,10 +4145,6 @@ closef_locked(struct fileproc *fp, struct fileglob *fg, proc_t p)
 }
 
 
-/* sleep address to permit wakeup of select by fileproc_drain() */
-extern int selwait;
-
-
 /*
  * fileproc_drain
  *
@@ -4025,7 +4184,7 @@ fileproc_drain(proc_t p, struct fileproc * fp)
                        (*fp->f_fglob->fg_ops->fo_drain)(fp, &context);
                }
                if (((fp->f_flags & FP_INSELECT)== FP_INSELECT)) {
-                       wait_queue_wakeup_all((wait_queue_t)fp->f_waddr, &selwait, THREAD_INTERRUPTED);
+                       wait_queue_wakeup_all((wait_queue_t)fp->f_waddr, NULL, THREAD_INTERRUPTED);
                } 
                p->p_fpdrainwait = 1;
 
@@ -4088,7 +4247,7 @@ fp_free(proc_t p, int fd, struct fileproc * fp)
  *             the entire file (l_whence = SEEK_SET, l_start = 0, l_len = 0).
  */
 int
-flock(proc_t p, struct flock_args *uap, __unused register_t *retval)
+flock(proc_t p, struct flock_args *uap, __unused int32_t *retval)
 {
        int fd = uap->fd;
        int how = uap->how;
@@ -4528,3 +4687,21 @@ fo_kqfilter(struct fileproc *fp, struct knote *kn, vfs_context_t ctx)
 {
         return ((*fp->f_ops->fo_kqfilter)(fp, kn, ctx));
 }
+
+/*
+ * The ability to send a file descriptor to another
+ * process is opt-in by file type.
+ */
+boolean_t
+filetype_issendable(file_type_t fdtype) 
+{
+       switch (fdtype) {
+               case DTYPE_VNODE:
+               case DTYPE_SOCKET:
+               case DTYPE_PIPE:
+                       return TRUE;
+               default:
+                       /* DTYPE_KQUEUE, DTYPE_FSEVENTS, DTYPE_PSXSHM, DTYPE_PSXSEM */
+                       return FALSE;
+       }
+}