> There has been developer pressure to permit an increasing number of
> ioctl's to pledged programs.  The problem is that providing a specific
> ioctl under a promise to one program, means it becomes supplied to all
> other programs that make that promise.  There is no discrete method
> to differentiate further, until now.
> 
> This proposal annotates file descriptors allocated before the first
> pledge(2) call in a process, with a marker.  Such file descriptors can
> be dup'd; the mark is retained.  They can fdpassed, which also retains
> the mark in the receiver (therefore, a non-pledged process can feed a
> pledged process).  Execve clears this flag.
> 
> That is the proposed semantic.  There are still a few glitches.
> 
> Once that mark exists, I feel more comfortable adding additional ioctl's
> which demand early-open fd's.  Specifically in privsep daemons.
> 
> 5 programs have been discovered in the tree which needed small changes
> (csh, ksh, less, tmux, dhclient).
> 
> less and tmux fixes are not commited, be cautious about tmux.

New version.

Index: sys/filedesc.h
===================================================================
RCS file: /cvs/src/sys/sys/filedesc.h,v
retrieving revision 1.30
diff -u -p -u -r1.30 filedesc.h
--- sys/filedesc.h      6 May 2015 08:52:17 -0000       1.30
+++ sys/filedesc.h      23 Jan 2017 16:00:14 -0000
@@ -105,6 +105,7 @@ struct filedesc0 {
  * Per-process open flags.
  */
 #define        UF_EXCLOSE      0x01            /* auto-close on exec */
+#define        UF_PLEDGED      0x02            /* opened after pledge(2) */
 
 /*
  * Flags on the file descriptor table.
@@ -121,7 +122,7 @@ struct filedesc0 {
  * Kernel global variables and routines.
  */
 void   filedesc_init(void);
-int    dupfdopen(struct filedesc *, int, int, int);
+int    dupfdopen(struct proc *p, struct filedesc *, int, int);
 int    fdalloc(struct proc *p, int want, int *result);
 void   fdexpand(struct proc *);
 int    falloc(struct proc *p, struct file **resultfp, int *resultfd);
Index: sys/pledge.h
===================================================================
RCS file: /cvs/src/sys/sys/pledge.h,v
retrieving revision 1.30
diff -u -p -u -r1.30 pledge.h
--- sys/pledge.h        23 Jan 2017 04:25:05 -0000      1.30
+++ sys/pledge.h        23 Jan 2017 11:40:58 -0000
@@ -126,7 +126,7 @@ int pledge_adjtime(struct proc *p, const
 int    pledge_sendit(struct proc *p, const void *to);
 int    pledge_sockopt(struct proc *p, int set, int level, int optname);
 int    pledge_socket(struct proc *p, int domain, int state);
-int    pledge_ioctl(struct proc *p, long com, struct file *);
+int    pledge_ioctl(struct proc *p, long com, struct file *, int, int);
 int    pledge_ioctl_drm(struct proc *p, long com, dev_t device);
 int    pledge_ioctl_vmm(struct proc *p, long com);
 int    pledge_flock(struct proc *p);
Index: sys/unpcb.h
===================================================================
RCS file: /cvs/src/sys/sys/unpcb.h,v
retrieving revision 1.12
diff -u -p -u -r1.12 unpcb.h
--- sys/unpcb.h 28 Aug 2015 04:38:47 -0000      1.12
+++ sys/unpcb.h 22 Jan 2017 09:19:54 -0000
@@ -86,17 +86,22 @@ struct      unpcb {
 #define        sotounpcb(so)   ((struct unpcb *)((so)->so_pcb))
 
 #ifdef _KERNEL
+struct fdpass {
+       struct file     *fp;
+       int             flags;
+};
+
 int    unp_attach(struct socket *);
 int    unp_bind(struct unpcb *, struct mbuf *, struct proc *);
 int    unp_connect(struct socket *, struct mbuf *, struct proc *);
 int    unp_connect2(struct socket *, struct socket *);
 void   unp_detach(struct unpcb *);
-void   unp_discard(struct file **, int);
+void   unp_discard(struct fdpass *, int);
 void   unp_disconnect(struct unpcb *);
 void   unp_drop(struct unpcb *, int);
 void   unp_gc(void *);
-void   unp_mark(struct file **, int);
-void   unp_scan(struct mbuf *, void (*)(struct file **, int));
+void   unp_mark(struct fdpass *, int);
+void   unp_scan(struct mbuf *, void (*)(struct fdpass *, int));
 void   unp_shutdown(struct unpcb *);
 int    unp_externalize(struct mbuf *, socklen_t, int);
 int    unp_internalize(struct mbuf *, struct proc *);
Index: kern/kern_descrip.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_descrip.c,v
retrieving revision 1.136
diff -u -p -u -r1.136 kern_descrip.c
--- kern/kern_descrip.c 24 Sep 2016 18:39:17 -0000      1.136
+++ kern/kern_descrip.c 23 Jan 2017 16:01:59 -0000
@@ -611,7 +611,7 @@ finishdup(struct proc *p, struct file *f
                FREF(oldfp);
 
        fdp->fd_ofiles[new] = fp;
-       fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] & ~UF_EXCLOSE;
+       fdp->fd_ofileflags[new] = fdp->fd_ofileflags[old] & 
~(UF_EXCLOSE|UF_PLEDGED);
        fp->f_count++;
        FRELE(fp, p);
        if (dup2 && oldfp == NULL)
@@ -632,6 +632,7 @@ fdremove(struct filedesc *fdp, int fd)
 {
        fdpassertlocked(fdp);
        fdp->fd_ofiles[fd] = NULL;
+       fdp->fd_ofileflags[fd] = 0;
        fd_unused(fdp, fd);
 }
 
@@ -805,6 +806,8 @@ restart:
                                fdp->fd_freefile = i;
                        *result = i;
                        fdp->fd_ofileflags[i] = 0;
+                       if (ISSET(p->p_p->ps_flags, PS_PLEDGE))
+                               fdp->fd_ofileflags[i] |= UF_PLEDGED;
                        return (0);
                }
        }
@@ -1253,7 +1256,7 @@ filedescopen(dev_t dev, int mode, int ty
  * Duplicate the specified descriptor to a free descriptor.
  */
 int
-dupfdopen(struct filedesc *fdp, int indx, int dfd, int mode)
+dupfdopen(struct proc *p, struct filedesc *fdp, int indx, int mode)
 {
        struct file *wfp;
 
@@ -1263,10 +1266,10 @@ dupfdopen(struct filedesc *fdp, int indx
         * Assume that the filename was user-specified; applications do
         * not tend to open /dev/fd/# when they can just call dup()
         */
-       if ((curproc->p_p->ps_flags & (PS_SUGIDEXEC | PS_SUGID))) {
-               if (curproc->p_descfd == 255)
+       if ((p->p_p->ps_flags & (PS_SUGIDEXEC | PS_SUGID))) {
+               if (p->p_descfd == 255)
                        return (EPERM);
-               if (curproc->p_descfd != curproc->p_dupfd)
+               if (p->p_descfd != p->p_dupfd)
                        return (EPERM);
        }
 
@@ -1277,7 +1280,7 @@ dupfdopen(struct filedesc *fdp, int indx
         * because fd_getfile will return NULL if the file at indx is
         * newly created by falloc (FIF_LARVAL).
         */
-       if ((wfp = fd_getfile(fdp, dfd)) == NULL)
+       if ((wfp = fd_getfile(fdp, p->p_dupfd)) == NULL)
                return (EBADF);
 
        /*
@@ -1291,7 +1294,9 @@ dupfdopen(struct filedesc *fdp, int indx
 
        fdp->fd_ofiles[indx] = wfp;
        fdp->fd_ofileflags[indx] = (fdp->fd_ofileflags[indx] & UF_EXCLOSE) |
-           (fdp->fd_ofileflags[dfd] & ~UF_EXCLOSE);
+           (fdp->fd_ofileflags[p->p_dupfd] & ~UF_EXCLOSE);
+       if (ISSET(p->p_p->ps_flags, PS_PLEDGE))
+               fdp->fd_ofileflags[indx] |= UF_PLEDGED;
        wfp->f_count++;
        fd_used(fdp, indx);
        return (0);
@@ -1307,9 +1312,11 @@ fdcloseexec(struct proc *p)
        int fd;
 
        fdplock(fdp);
-       for (fd = 0; fd <= fdp->fd_lastfile; fd++)
+       for (fd = 0; fd <= fdp->fd_lastfile; fd++) {
+               fdp->fd_ofileflags[fd] &= ~UF_PLEDGED;
                if (fdp->fd_ofileflags[fd] & UF_EXCLOSE)
                        (void) fdrelease(p, fd);
+       }
        fdpunlock(fdp);
 }
 
Index: kern/kern_pledge.c
===================================================================
RCS file: /cvs/src/sys/kern/kern_pledge.c,v
retrieving revision 1.192
diff -u -p -u -r1.192 kern_pledge.c
--- kern/kern_pledge.c  23 Jan 2017 05:49:24 -0000      1.192
+++ kern/kern_pledge.c  23 Jan 2017 14:39:51 -0000
@@ -66,6 +66,7 @@
 
 #include "audio.h"
 #include "pf.h"
+#include "bpfilter.h"
 #include "pty.h"
 
 #if defined(__amd64__) || defined(__i386__)
@@ -401,8 +402,9 @@ sys_pledge(struct proc *p, void *v, regi
                syscallarg(const char **)paths;
        } */    *uap = v;
        struct process *pr = p->p_p;
+       struct filedesc *fdp = p->p_fd;
        uint64_t flags = 0;
-       int error;
+       int error, fd;
 
        if (SCARG(uap, request)) {
                size_t rbuflen;
@@ -538,6 +540,19 @@ sys_pledge(struct proc *p, void *v, regi
        }
 
        if (SCARG(uap, request)) {
+#ifdef DIAGNOSTIC
+               if (!ISSET(pr->ps_flags, PS_PLEDGE)) {
+                       fdplock(fdp);
+                       for (fd = 0; fd <= fdp->fd_lastfile; fd++) {
+                               if (fdp->fd_ofiles[fd] &&
+                                   (fdp->fd_ofileflags[fd] & UF_PLEDGED))
+                                       printf("%s: fd %d was set!\n",
+                                           pr->ps_comm, fd);
+                               fdp->fd_ofileflags[fd] &= ~UF_PLEDGED;
+                       }
+                       fdpunlock(fdp);
+               }
+#endif
                pr->ps_pledge = flags;
                pr->ps_flags |= PS_PLEDGE;
        }
@@ -1102,7 +1117,7 @@ pledge_sendit(struct proc *p, const void
 }
 
 int
-pledge_ioctl(struct proc *p, long com, struct file *fp)
+pledge_ioctl(struct proc *p, long com, struct file *fp, int fd, int fdpledged)
 {
        struct vnode *vp = NULL;
        int error = EPERM;
@@ -1130,6 +1145,7 @@ pledge_ioctl(struct proc *p, long com, s
 
        if ((p->p_p->ps_pledge & PLEDGE_INET)) {
                switch (com) {
+               case SIOCGIFDATA:
                case SIOCGIFGROUP:
                        if (fp->f_type == DTYPE_SOCKET)
                                return (0);
@@ -1139,19 +1155,22 @@ pledge_ioctl(struct proc *p, long com, s
 
        if ((p->p_p->ps_pledge & PLEDGE_BPF)) {
                switch (com) {
-               case BIOCGSTATS:        /* bpf: tcpdump privsep on ^C */
-                       if (fp->f_type == DTYPE_VNODE &&
-                           fp->f_ops->fo_ioctl == vn_ioctl)
+#if NBPFILTER > 0
+               case BIOCGSTATS:        /* tcpdump, pflogd */
+                       if (!fdpledged &&
+                           fp->f_type == DTYPE_VNODE &&
+                           vp->v_type == VCHR &&
+                           cdevsw[major(vp->v_rdev)].d_open == bpfopen)
                                return (0);
                        break;
+#endif
                }
        }
 
        if ((p->p_p->ps_pledge & PLEDGE_TAPE)) {
                switch (com) {
-               case MTIOCGET:
+               case MTIOCGET:          /* pax */
                case MTIOCTOP:
-                       /* for pax(1) and such, checking tapes... */
                        if (fp->f_type == DTYPE_VNODE &&
                            (vp->v_type == VCHR || vp->v_type == VBLK))
                                return (0);
@@ -1189,14 +1208,17 @@ pledge_ioctl(struct proc *p, long com, s
 
        if ((p->p_p->ps_pledge & PLEDGE_DISKLABEL)) {
                switch (com) {
-               case DIOCGDINFO:
-               case DIOCGPDINFO:
-               case DIOCRLDINFO:
+               case DIOCRLDINFO:       /* change operations, etc. */
                case DIOCWDINFO:
                case BIOCDISK:
                case BIOCINQ:
                case BIOCINSTALLBOOT:
                case BIOCVOL:
+                       if (fdpledged)
+                               break;
+                       /* FALLTHROUGH */
+               case DIOCGDINFO:        /* read operations, etc. */
+               case DIOCGPDINFO:
                        if (fp->f_type == DTYPE_VNODE &&
                            ((vp->v_type == VCHR &&
                            cdevsw[major(vp->v_rdev)].d_type == D_DISK) ||
@@ -1216,7 +1238,7 @@ pledge_ioctl(struct proc *p, long com, s
        if ((p->p_p->ps_pledge & PLEDGE_PF)) {
 #if NPF > 0
                switch (com) {
-               case DIOCADDRULE:
+               case DIOCADDRULE:       /* relayd */
                case DIOCGETSTATUS:
                case DIOCNATLOOK:
                case DIOCRADDTABLES:
@@ -1225,10 +1247,14 @@ pledge_ioctl(struct proc *p, long com, s
                case DIOCRCLRTSTATS:
                case DIOCRGETTSTATS:
                case DIOCRSETADDRS:
-               case DIOCXBEGIN:
+               case DIOCXBEGIN:        /* relayd, proxies */
                case DIOCXCOMMIT:
                case DIOCKILLSRCNODES:
-                       if ((fp->f_type == DTYPE_VNODE) &&
+               case DIOCRGETASTATS:    /* bgpd */
+               case DIOCRDELADDRS:
+               case DIOCRADDADDRS:
+                       if (!fdpledged &&
+                           (fp->f_type == DTYPE_VNODE) &&
                            (vp->v_type == VCHR) &&
                            (cdevsw[major(vp->v_rdev)].d_open == pfopen))
                                return (0);
@@ -1240,26 +1266,27 @@ pledge_ioctl(struct proc *p, long com, s
        if ((p->p_p->ps_pledge & PLEDGE_TTY)) {
                switch (com) {
 #if NPTY > 0
-               case PTMGET:
-                       if ((p->p_p->ps_pledge & PLEDGE_RPATH) == 0)
-                               break;
-                       if ((p->p_p->ps_pledge & PLEDGE_WPATH) == 0)
-                               break;
-                       if (fp->f_type != DTYPE_VNODE || vp->v_type != VCHR)
-                               break;
-                       if (cdevsw[major(vp->v_rdev)].d_open != ptmopen)
-                               break;
-                       return (0);
+               case PTMGET:            /* tmux */
+                       if (!fdpledged &&
+                           (p->p_p->ps_pledge & PLEDGE_RPATH) &&
+                           (p->p_p->ps_pledge & PLEDGE_WPATH) &&
+                           fp->f_type == DTYPE_VNODE && vp->v_type == VCHR &&
+                           cdevsw[major(vp->v_rdev)].d_open == ptmopen)
+                               return (0);
+                       break;
 #endif /* NPTY > 0 */
-               case TIOCSTI:           /* ksh? csh? */
-                       if ((p->p_p->ps_pledge & PLEDGE_PROC) &&
+               case TIOCSTI:           /* csh */
+                       if (!fdpledged &&
+                           (p->p_p->ps_pledge & PLEDGE_PROC) &&
                            fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY))
                                return (0);
                        break;
                case TIOCSPGRP:
-                       if ((p->p_p->ps_pledge & PLEDGE_PROC) == 0)
-                               break;
-                       /* FALLTHROUGH */
+                       /* cannot do !fdpledged test */
+                       if ((p->p_p->ps_pledge & PLEDGE_PROC) &&
+                           fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY))
+                               return (0);
+                       break;
                case TIOCFLUSH:         /* getty, telnet */
                case TIOCGPGRP:
                case TIOCGETA:
@@ -1267,7 +1294,7 @@ pledge_ioctl(struct proc *p, long com, s
                        if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY))
                                return (0);
                        return (ENOTTY);
-               case TIOCSWINSZ:
+               case TIOCSWINSZ:        /* tmux, script */
                case TIOCEXT:           /* mail, libedit .. */
                case TIOCCBRK:          /* cu */
                case TIOCSBRK:          /* cu */
@@ -1275,7 +1302,7 @@ pledge_ioctl(struct proc *p, long com, s
                case TIOCSDTR:          /* cu */
                case TIOCEXCL:          /* cu */
                case TIOCSETA:          /* cu, ... */
-               case TIOCSETAW:         /* cu, ... */
+               case TIOCSETAW:         /* tmux, cu, ksh ... */
                case TIOCSETAF:         /* tcsetattr TCSAFLUSH, script */
                case TIOCSCTTY:         /* forkpty(3), login_tty(3), ... */
                        if (fp->f_type == DTYPE_VNODE && (vp->v_flag & VISTTY))
@@ -1296,7 +1323,7 @@ pledge_ioctl(struct proc *p, long com, s
                case SIOCGNBRINFO_IN6:
                case SIOCGIFINFO_IN6:
                case SIOCGIFMEDIA:
-                       if (fp->f_type == DTYPE_SOCKET)
+                       if (!fdpledged && fp->f_type == DTYPE_SOCKET)
                                return (0);
                        break;
                }
@@ -1314,6 +1341,8 @@ pledge_ioctl(struct proc *p, long com, s
 #endif
        }
 
+       if (fdpledged)
+               printf("%s: ioctl %08lx post-pledge fd %d\n", p->p_p->ps_comm, 
com, fd);
        return pledge_fail(p, error, PLEDGE_TTY);
 }
 
Index: kern/sys_generic.c
===================================================================
RCS file: /cvs/src/sys/kern/sys_generic.c,v
retrieving revision 1.113
diff -u -p -u -r1.113 sys_generic.c
--- kern/sys_generic.c  7 Nov 2016 00:26:33 -0000       1.113
+++ kern/sys_generic.c  23 Jan 2017 13:34:18 -0000
@@ -390,17 +390,20 @@ sys_ioctl(struct proc *p, void *v, regis
                syscallarg(void *) data;
        } */ *uap = v;
        struct file *fp;
-       struct filedesc *fdp;
+       struct filedesc *fdp = p->p_fd;
        u_long com = SCARG(uap, com);
        int error;
        u_int size;
        caddr_t data, memp;
-       int tmp;
+       int tmp, pl;
 #define STK_PARAMS     128
        long long stkbuf[STK_PARAMS / sizeof(long long)];
 
-       fdp = p->p_fd;
+       fdplock(fdp);
        fp = fd_getfile_mode(fdp, SCARG(uap, fd), FREAD|FWRITE);
+       if (fp)
+               pl = fdp->fd_ofileflags[SCARG(uap, fd)] & UF_PLEDGED;
+       fdpunlock(fdp);
 
        if (fp == NULL)
                return (EBADF);
@@ -412,7 +415,7 @@ sys_ioctl(struct proc *p, void *v, regis
                        return (EINVAL);
        }
 
-       error = pledge_ioctl(p, com, fp);
+       error = pledge_ioctl(p, com, fp, SCARG(uap, fd), pl);
        if (error)
                return (error);
 
Index: kern/uipc_usrreq.c
===================================================================
RCS file: /cvs/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.109
diff -u -p -u -r1.109 uipc_usrreq.c
--- kern/uipc_usrreq.c  29 Dec 2016 12:12:43 -0000      1.109
+++ kern/uipc_usrreq.c  23 Jan 2017 16:17:00 -0000
@@ -63,8 +63,8 @@ LIST_HEAD(unp_head, unpcb) unp_head = LI
 struct unp_deferral {
        SLIST_ENTRY(unp_deferral)       ud_link;
        int     ud_n;
-       /* followed by ud_n struct file * pointers */
-       struct file *ud_fp[];
+       /* followed by ud_n struct fdpass */
+       struct fdpass ud_fp[];
 };
 
 /* list of sets of files that were sent over sockets that are now closed */
@@ -664,12 +664,12 @@ unp_externalize(struct mbuf *rights, soc
        struct proc *p = curproc;               /* XXX */
        struct cmsghdr *cm = mtod(rights, struct cmsghdr *);
        int i, *fdp = NULL;
-       struct file **rp;
+       struct fdpass *rp;
        struct file *fp;
        int nfds, error = 0;
 
        nfds = (cm->cmsg_len - CMSG_ALIGN(sizeof(*cm))) /
-           sizeof(struct file *);
+           sizeof(struct fdpass);
        if (controllen < CMSG_ALIGN(sizeof(struct cmsghdr)))
                controllen = 0;
        else
@@ -680,9 +680,10 @@ unp_externalize(struct mbuf *rights, soc
        }
 
        /* Make sure the recipient should be able to see the descriptors.. */
-       rp = (struct file **)CMSG_DATA(cm);
+       rp = (struct fdpass *)CMSG_DATA(cm);
        for (i = 0; i < nfds; i++) {
-               fp = *rp++;
+               fp = rp->fp;
+               rp++;
                error = pledge_recvfd(p, fp);
                if (error)
                        break;
@@ -709,7 +710,7 @@ restart:
        fdplock(p->p_fd);
        if (error != 0) {
                if (nfds > 0) {
-                       rp = ((struct file **)CMSG_DATA(cm));
+                       rp = ((struct fdpass *)CMSG_DATA(cm));
                        unp_discard(rp, nfds);
                }
                goto out;
@@ -719,7 +720,7 @@ restart:
         * First loop -- allocate file descriptor table slots for the
         * new descriptors.
         */
-       rp = ((struct file **)CMSG_DATA(cm));
+       rp = ((struct fdpass *)CMSG_DATA(cm));
        for (i = 0; i < nfds; i++) {
                if ((error = fdalloc(p, 0, &fdp[i])) != 0) {
                        /*
@@ -748,7 +749,9 @@ restart:
                 * fdalloc() works properly.. We finalize it all
                 * in the loop below.
                 */
-               p->p_fd->fd_ofiles[fdp[i]] = *rp++;
+               p->p_fd->fd_ofiles[fdp[i]] = rp->fp;
+               p->p_fd->fd_ofileflags[fdp[i]] = (rp->flags & UF_PLEDGED);
+               rp++;
 
                if (flags & MSG_CMSG_CLOEXEC)
                        p->p_fd->fd_ofileflags[fdp[i]] |= UF_EXCLOSE;
@@ -758,11 +761,12 @@ restart:
         * Now that adding them has succeeded, update all of the
         * descriptor passing state.
         */
-       rp = (struct file **)CMSG_DATA(cm);
+       rp = (struct fdpass *)CMSG_DATA(cm);
        for (i = 0; i < nfds; i++) {
                struct unpcb *unp;
 
-               fp = *rp++;
+               fp = rp->fp;
+               rp++;
                if ((unp = fptounp(fp)) != NULL)
                        unp->unp_msgcount--;
                unp_rights--;
@@ -787,7 +791,8 @@ unp_internalize(struct mbuf *control, st
 {
        struct filedesc *fdp = p->p_fd;
        struct cmsghdr *cm = mtod(control, struct cmsghdr *);
-       struct file **rp, *fp;
+       struct fdpass *rp;
+       struct file *fp;
        struct unpcb *unp;
        int i, error;
        int nfds, *ip, fd, neededspace;
@@ -807,7 +812,7 @@ unp_internalize(struct mbuf *control, st
 
        /* Make sure we have room for the struct file pointers */
 morespace:
-       neededspace = CMSG_SPACE(nfds * sizeof(struct file *)) -
+       neededspace = CMSG_SPACE(nfds * sizeof(struct fdpass)) -
            control->m_len;
        if (neededspace > M_TRAILINGSPACE(control)) {
                char *tmp;
@@ -834,11 +839,11 @@ morespace:
        }
 
        /* adjust message & mbuf to note amount of space actually used. */
-       cm->cmsg_len = CMSG_LEN(nfds * sizeof(struct file *));
-       control->m_len = CMSG_SPACE(nfds * sizeof(struct file *));
+       cm->cmsg_len = CMSG_LEN(nfds * sizeof(struct fdpass));
+       control->m_len = CMSG_SPACE(nfds * sizeof(struct fdpass));
 
        ip = ((int *)CMSG_DATA(cm)) + nfds - 1;
-       rp = ((struct file **)CMSG_DATA(cm)) + nfds - 1;
+       rp = ((struct fdpass *)CMSG_DATA(cm)) + nfds - 1;
        for (i = 0; i < nfds; i++) {
                memcpy(&fd, ip, sizeof fd);
                ip--;
@@ -859,7 +864,8 @@ morespace:
                        error = EINVAL;
                        goto fail;
                }
-               memcpy(rp, &fp, sizeof fp);
+               rp->fp = fp;
+               rp->flags = fdp->fd_ofileflags[fd] & UF_PLEDGED;
                rp--;
                fp->f_count++;
                if ((unp = fptounp(fp)) != NULL) {
@@ -873,7 +879,7 @@ fail:
        /* Back out what we just did. */
        for ( ; i > 0; i--) {
                rp++;
-               memcpy(&fp, rp, sizeof(fp));
+               fp = rp->fp;
                fp->f_count--;
                if ((unp = fptounp(fp)) != NULL)
                        unp->unp_msgcount--;
@@ -902,7 +908,7 @@ unp_gc(void *arg __unused)
        while ((defer = SLIST_FIRST(&unp_deferred)) != NULL) {
                SLIST_REMOVE_HEAD(&unp_deferred, ud_link);
                for (i = 0; i < defer->ud_n; i++) {
-                       fp = defer->ud_fp[i];
+                       fp = defer->ud_fp[i].fp;
                        if (fp == NULL)
                                continue;
                        FREF(fp);
@@ -911,7 +917,7 @@ unp_gc(void *arg __unused)
                        unp_rights--;
                        (void) closef(fp, NULL);
                }
-               free(defer, M_TEMP, sizeof(*defer) + sizeof(fp) * defer->ud_n);
+               free(defer, M_TEMP, sizeof(*defer) + sizeof(struct fdpass) * 
defer->ud_n);
        }
 
        unp_defer = 0;
@@ -1005,10 +1011,10 @@ unp_dispose(struct mbuf *m)
 }
 
 void
-unp_scan(struct mbuf *m0, void (*op)(struct file **, int))
+unp_scan(struct mbuf *m0, void (*op)(struct fdpass *, int))
 {
        struct mbuf *m;
-       struct file **rp;
+       struct fdpass *rp;
        struct cmsghdr *cm;
        int qfds;
 
@@ -1021,9 +1027,9 @@ unp_scan(struct mbuf *m0, void (*op)(str
                                    cm->cmsg_type != SCM_RIGHTS)
                                        continue;
                                qfds = (cm->cmsg_len - CMSG_ALIGN(sizeof *cm))
-                                   / sizeof(struct file *);
+                                   / sizeof(struct fdpass);
                                if (qfds > 0) {
-                                       rp = (struct file **)CMSG_DATA(cm);
+                                       rp = (struct fdpass *)CMSG_DATA(cm);
                                        op(rp, qfds);
                                }
                                break;          /* XXX, but saves time */
@@ -1034,16 +1040,16 @@ unp_scan(struct mbuf *m0, void (*op)(str
 }
 
 void
-unp_mark(struct file **rp, int nfds)
+unp_mark(struct fdpass *rp, int nfds)
 {
        struct unpcb *unp;
        int i;
 
        for (i = 0; i < nfds; i++) {
-               if (rp[i] == NULL)
+               if (rp[i].fp == NULL)
                        continue;
 
-               unp = fptounp(rp[i]);
+               unp = fptounp(rp[i].fp);
                if (unp == NULL)
                        continue;
 
@@ -1057,7 +1063,7 @@ unp_mark(struct file **rp, int nfds)
 }
 
 void
-unp_discard(struct file **rp, int nfds)
+unp_discard(struct fdpass *rp, int nfds)
 {
        struct unp_deferral *defer;
 
Index: kern/vfs_syscalls.c
===================================================================
RCS file: /cvs/src/sys/kern/vfs_syscalls.c,v
retrieving revision 1.268
diff -u -p -u -r1.268 vfs_syscalls.c
--- kern/vfs_syscalls.c 15 Jan 2017 23:18:05 -0000      1.268
+++ kern/vfs_syscalls.c 23 Jan 2017 15:59:48 -0000
@@ -829,7 +829,7 @@ doopenat(struct proc *p, int fd, const c
                if (error == ENODEV &&
                    p->p_dupfd >= 0 &&                  /* XXX from fdopen */
                    (error =
-                       dupfdopen(fdp, indx, p->p_dupfd, flags)) == 0) {
+                       dupfdopen(p, fdp, indx, flags)) == 0) {
                        closef(fp, p);
                        *retval = indx;
                        goto out;

Reply via email to