Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/compat/netbsd32 Reduce difference between recvfrom/recvm...



details:   https://anonhg.NetBSD.org/src/rev/2052940106f2
branches:  trunk
changeset: 772715:2052940106f2
user:      joerg <joerg%NetBSD.org@localhost>
date:      Fri Jan 13 21:02:03 2012 +0000

description:
Reduce difference between recvfrom/recvmsg for netbsd32 and the native
version. This fixes the bug of lost file descriptors when the control
space is not large enough.

diffstat:

 sys/compat/netbsd32/netbsd32_socket.c |  211 +++++++++------------------------
 1 files changed, 62 insertions(+), 149 deletions(-)

diffs (266 lines):

diff -r 2de3e5294594 -r 2052940106f2 sys/compat/netbsd32/netbsd32_socket.c
--- a/sys/compat/netbsd32/netbsd32_socket.c     Fri Jan 13 16:50:28 2012 +0000
+++ b/sys/compat/netbsd32/netbsd32_socket.c     Fri Jan 13 21:02:03 2012 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: netbsd32_socket.c,v 1.37 2010/04/23 15:19:20 rmind Exp $       */
+/*     $NetBSD: netbsd32_socket.c,v 1.38 2012/01/13 21:02:03 joerg Exp $       */
 
 /*
  * Copyright (c) 1998, 2001 Matthew R. Green
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_socket.c,v 1.37 2010/04/23 15:19:20 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_socket.c,v 1.38 2012/01/13 21:02:03 joerg Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -49,12 +49,9 @@
 #include <compat/netbsd32/netbsd32_conv.h>
 
 /*
- * Note that the netbsd32_msghdr's iov really points to a struct iovec,
- * not a netbsd32_iovec.
+ * XXX Assumes that sockaddr is compatible.
+ * XXX Assumes that copyout_msg_control uses identical alignment.
  */
-static int recvit32(struct lwp *, int, struct netbsd32_msghdr *,
-    struct iovec *, void *, register_t *);
-
 int
 netbsd32_recvmsg(struct lwp *l, const struct netbsd32_recvmsg_args *uap, register_t *retval)
 {
@@ -63,147 +60,61 @@
                syscallarg(netbsd32_msghdrp_t) msg;
                syscallarg(int) flags;
        } */
-       struct netbsd32_msghdr msg;
+       struct netbsd32_msghdr  msg32;
        struct iovec aiov[UIO_SMALLIOV], *iov;
-       struct netbsd32_iovec *iov32;
+       struct msghdr   msg;
+       int             error;
+       struct mbuf     *from, *control;
        size_t iovsz;
-       int error;
 
-       error = copyin(SCARG_P32(uap, msg), &msg, sizeof(msg));
-               /* netbsd32_msghdr needs the iov pre-allocated */
+       error = copyin(SCARG_P32(uap, msg), &msg32, sizeof(msg32));
        if (error)
                return (error);
-       iovsz = msg.msg_iovlen * sizeof(struct iovec);
-       if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) {
-               if ((u_int)msg.msg_iovlen > IOV_MAX)
+
+       iovsz = msg32.msg_iovlen * sizeof(struct iovec);
+       if (msg32.msg_iovlen > UIO_SMALLIOV) {
+               if (msg32.msg_iovlen > IOV_MAX)
                        return (EMSGSIZE);
                iov = kmem_alloc(iovsz, KM_SLEEP);
        } else 
                iov = aiov;
-       msg.msg_flags = SCARG(uap, flags);
-       iov32 = NETBSD32PTR64(msg.msg_iov);
-       error = netbsd32_to_iovecin(iov32, iov, msg.msg_iovlen);
+       error = netbsd32_to_iovecin(NETBSD32PTR64(msg32.msg_iov), iov,
+           msg32.msg_iovlen);
        if (error)
                goto done;
-       if ((error = recvit32(l, SCARG(uap, s), &msg, iov, (void *)0,
-           retval)) == 0) {
-               error = copyout(&msg, SCARG_P32(uap, msg), sizeof(msg));
-       }
-done:
-       if (iov != aiov)
-               kmem_free(iov, iovsz);
-       return (error);
-}
 
-int
-recvit32(struct lwp *l, int s, struct netbsd32_msghdr *mp, struct iovec *iov, void *namelenp, register_t *retsize)
-{
-       struct uio auio;
-       struct mbuf *from = 0, *control = 0;
-       struct socket *so;
-       struct iovec *ktriov = NULL;
-       size_t len, iovsz;
-       int i, error;
+       msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
+       msg.msg_name = NETBSD32PTR64(msg32.msg_name);
+       msg.msg_namelen = msg32.msg_namelen;
+       msg.msg_control = NETBSD32PTR64(msg32.msg_control);
+       msg.msg_controllen = msg32.msg_controllen;
+       msg.msg_iov = iov;
+       msg.msg_iovlen = msg32.msg_iovlen;
+
+       error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from,
+           msg.msg_control != NULL ? &control : NULL, retval);
+       if (error != 0)
+               goto done;
 
-       /* fd_getsock() will use the descriptor for us */
-       if ((error = fd_getsock(s, &so)) != 0)
-               return (error);
-       auio.uio_iov = iov;
-       auio.uio_iovcnt = mp->msg_iovlen;
-       auio.uio_rw = UIO_READ;
-       auio.uio_vmspace = l->l_proc->p_vmspace;
-       auio.uio_offset = 0;                    /* XXX */
-       auio.uio_resid = 0;
-       for (i = 0; i < mp->msg_iovlen; i++, iov++) {
-               /*
-                * Reads return ssize_t because -1 is returned on error.
-                * Therefore we must restrict the length to SSIZE_MAX to
-                * avoid garbage return values.
-                */
-               auio.uio_resid += iov->iov_len;
-               if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) {
-                       error = EINVAL;
-                       goto out1;
-               }
-       }
+       if (msg.msg_control != NULL)
+               error = copyout_msg_control(l, &msg, control);
 
-       iovsz = mp->msg_iovlen * sizeof(struct iovec);
-       if (ktrpoint(KTR_GENIO)) {
-               ktriov = kmem_alloc(iovsz, KM_SLEEP);
-               memcpy(ktriov, auio.uio_iov, iovsz);
+       if (error == 0)
+               error = copyout_sockname(msg.msg_name, &msg.msg_namelen, 0,
+                       from);
+       if (from != NULL)
+               m_free(from);
+       if (error == 0) {
+               ktrkuser("msghdr", &msg, sizeof msg);
+               msg32.msg_namelen = msg.msg_namelen;
+               msg32.msg_controllen = msg.msg_controllen;
+               msg32.msg_flags = msg.msg_flags;
+               error = copyout(&msg32, SCARG_P32(uap, msg), sizeof(msg32));
        }
 
-       len = auio.uio_resid;
-       error = (*so->so_receive)(so, &from, &auio, NULL,
-                         NETBSD32PTR64(mp->msg_control) ? &control : NULL,
-                         &mp->msg_flags);
-       if (error) {
-               if (auio.uio_resid != len && (error == ERESTART ||
-                   error == EINTR || error == EWOULDBLOCK))
-                       error = 0;
-       }
-
-       if (ktriov != NULL) {
-               ktrgeniov(s, UIO_READ, ktriov, len - auio.uio_resid, error);
-               kmem_free(ktriov, iovsz);
-       }
-
-       if (error)
-               goto out;
-       *retsize = len - auio.uio_resid;
-       if (NETBSD32PTR64(mp->msg_name)) {
-               len = mp->msg_namelen;
-               if (len <= 0 || from == 0)
-                       len = 0;
-               else {
-                       if (len > from->m_len)
-                               len = from->m_len;
-                       /* else if len < from->m_len ??? */
-                       error = copyout(mtod(from, void *),
-                           (void *)NETBSD32PTR64(mp->msg_name),
-                           (unsigned)len);
-                       if (error)
-                               goto out;
-               }
-               mp->msg_namelen = len;
-               if (namelenp &&
-                   (error = copyout((void *)&len, namelenp, sizeof(int))))
-                       goto out;
-       }
-       if (NETBSD32PTR64(mp->msg_control)) {
-               len = mp->msg_controllen;
-               if (len <= 0 || control == 0)
-                       len = 0;
-               else {
-                       struct mbuf *m = control;
-                       void *cp = (void *)NETBSD32PTR64(mp->msg_control);
-
-                       do {
-                               i = m->m_len;
-                               if (len < i) {
-                                       mp->msg_flags |= MSG_CTRUNC;
-                                       i = len;
-                               }
-                               error = copyout(mtod(m, void *), cp,
-                                   (unsigned)i);
-                               if (m->m_next)
-                                       i = ALIGN(i);
-                               cp = (char *)cp + i;
-                               len -= i;
-                               if (error != 0 || len <= 0)
-                                       break;
-                       } while ((m = m->m_next) != NULL);
-                       len = (char *)cp - (char *)NETBSD32PTR64(mp->msg_control);
-               }
-               mp->msg_controllen = len;
-       }
- out:
-       if (from)
-               m_freem(from);
-       if (control)
-               m_freem(control);
- out1:
-       fd_putfile(s);
+ done:
+       if (iov != aiov)
+               kmem_free(iov, iovsz);
        return (error);
 }
 
@@ -262,26 +173,28 @@
                syscallarg(netbsd32_sockaddrp_t) from;
                syscallarg(netbsd32_intp) fromlenaddr;
        } */
-       struct netbsd32_msghdr msg;
-       struct iovec aiov;
-       int error;
+       struct msghdr   msg;
+       struct iovec    aiov;
+       int             error;
+       struct mbuf     *from;
 
-       if (SCARG_P32(uap, fromlenaddr)) {
-               error = copyin(SCARG_P32(uap, fromlenaddr),
-                   &msg.msg_namelen, sizeof(msg.msg_namelen));
-               if (error)
-                       return (error);
-       } else
-               msg.msg_namelen = 0;
-       msg.msg_name = SCARG(uap, from);
-       NETBSD32PTR32(msg.msg_iov, 0); /* ignored in recvit32(), uses iov */
+       msg.msg_name = NULL;
+       msg.msg_iov = &aiov;
        msg.msg_iovlen = 1;
        aiov.iov_base = SCARG_P32(uap, buf);
-       aiov.iov_len = (u_long)SCARG(uap, len);
-       NETBSD32PTR32(msg.msg_control, 0);
-       msg.msg_flags = SCARG(uap, flags);
-       return (recvit32(l, SCARG(uap, s), &msg, &aiov,
-           SCARG_P32(uap, fromlenaddr), retval));
+       aiov.iov_len = SCARG(uap, len);
+       msg.msg_control = NULL;
+       msg.msg_flags = SCARG(uap, flags) & MSG_USERFLAGS;
+
+       error = do_sys_recvmsg(l, SCARG(uap, s), &msg, &from, NULL, retval);
+       if (error != 0)
+               return error;
+
+       error = copyout_sockname(SCARG_P32(uap, from), SCARG_P32(uap, fromlenaddr),
+           MSG_LENUSRSPACE, from);
+       if (from != NULL)
+               m_free(from);
+       return error;
 }
 
 int



Home | Main Index | Thread Index | Old Index