File descriptor passing internalizes process fd's to an array of
struct file *.  This results in tricky pointer management.

How about passing it as an array of structs instead.  Only one field
inside for now, struct file *.  However soon I'll need to pass additional
fields along with the file, and I didn't want to use the low bits of the
pointer :)

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 23:02:15 -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,8 @@ 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;
+               rp++;
 
                if (flags & MSG_CMSG_CLOEXEC)
                        p->p_fd->fd_ofileflags[fdp[i]] |= UF_EXCLOSE;
@@ -758,11 +760,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 +790,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 +811,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 +838,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 +863,7 @@ morespace:
                        error = EINVAL;
                        goto fail;
                }
-               memcpy(rp, &fp, sizeof fp);
+               rp->fp = fp;
                rp--;
                fp->f_count++;
                if ((unp = fptounp(fp)) != NULL) {
@@ -873,7 +877,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 +906,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 +915,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 +1009,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 +1025,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 +1038,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 +1061,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: 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 23 Jan 2017 23:01:51 -0000
@@ -86,17 +86,21 @@ struct      unpcb {
 #define        sotounpcb(so)   ((struct unpcb *)((so)->so_pcb))
 
 #ifdef _KERNEL
+struct fdpass {
+       struct file     *fp;
+};
+
 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 *);

Reply via email to