Index: kern/uipc_syscalls.c =================================================================== RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/kern/uipc_syscalls.c,v retrieving revision 1.16 diff -u -u -r1.16 uipc_syscalls.c --- kern/uipc_syscalls.c 29 Sep 2003 05:34:08 -0000 1.16 +++ kern/uipc_syscalls.c 2 Oct 2003 06:14:13 -0000 @@ -518,18 +518,13 @@ return (error); } -/* - * This function never touches mp->msg_namelen. - */ int -kern_sendmsg(int s, struct msghdr *mp, int *res) +kern_sendmsg(int s, struct sockaddr *sa, struct uio *auio, + struct mbuf *control, int flags, int *res) { struct thread *td = curthread; struct proc *p = td->td_proc; struct file *fp; - struct uio auio; - struct iovec *iov; - int i; int len, error; struct socket *so; #ifdef KTRACE @@ -540,35 +535,21 @@ error = holdsock(p->p_fd, s, &fp); if (error) return (error); - auio.uio_iov = mp->msg_iov; - auio.uio_iovcnt = mp->msg_iovlen; - auio.uio_segflg = UIO_USERSPACE; - auio.uio_rw = UIO_WRITE; - auio.uio_td = td; - auio.uio_offset = 0; /* XXX */ - auio.uio_resid = 0; - iov = mp->msg_iov; - for (i = 0; i < mp->msg_iovlen; i++, iov++) { - if ((auio.uio_resid += iov->iov_len) < 0) { - fdrop(fp, td); - return (EINVAL); - } - } #ifdef KTRACE if (KTRPOINT(td, KTR_GENIO)) { - int iovlen = auio.uio_iovcnt * sizeof (struct iovec); + int iovlen = auio->uio_iovcnt * sizeof (struct iovec); MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); - bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); - ktruio = auio; + bcopy((caddr_t)auio->uio_iov, (caddr_t)ktriov, iovlen); + ktruio = *auio; } #endif - len = auio.uio_resid; + len = auio->uio_resid; so = (struct socket *)fp->f_data; - error = so->so_proto->pr_usrreqs->pru_sosend(so, mp->msg_name, - &auio, NULL, mp->msg_control, mp->msg_flags, td); + error = so->so_proto->pr_usrreqs->pru_sosend(so, sa, auio, NULL, + control, flags, td); if (error) { - if (auio.uio_resid != len && (error == ERESTART || + if (auio->uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; if (error == EPIPE) @@ -578,14 +559,14 @@ if (ktriov != NULL) { if (error == 0) { ktruio.uio_iov = ktriov; - ktruio.uio_resid = len - auio.uio_resid; + ktruio.uio_resid = len - auio->uio_resid; ktrgenio(p->p_tracep, s, UIO_WRITE, &ktruio, error); } FREE(ktriov, M_TEMP); } #endif if (error == 0) - *res = len - auio.uio_resid; + *res = len - auio->uio_resid; fdrop(fp, td); return (error); } @@ -596,7 +577,8 @@ int sendto(struct sendto_args *uap) { - struct msghdr msg; + struct thread *td = curthread; + struct uio auio; struct iovec aiov; struct sockaddr *sa = NULL; int error; @@ -605,19 +587,19 @@ error = getsockaddr(&sa, uap->to, uap->tolen); if (error) return (error); - msg.msg_name = sa; - } else { - msg.msg_name = NULL; } - /* msg.msg_namelen is ignored by kern_sendmsg() */ - msg.msg_iov = &aiov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_flags = uap->flags; aiov.iov_base = uap->buf; aiov.iov_len = uap->len; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_offset = 0; + auio.uio_resid = uap->len; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_WRITE; + auio.uio_td = td; - error = kern_sendmsg(uap->s, &msg, &uap->sysmsg_result); + error = kern_sendmsg(uap->s, sa, &auio, NULL, uap->flags, + &uap->sysmsg_result); if (sa) FREE(sa, M_SONAME); @@ -626,19 +608,17 @@ /* * sendmsg_args(int s, caddr_t msg, int flags) - * - * We must copyin the msghdr and copyin a bunch of it's fields. We - * explicitly copyin msg.msg_iov and conditionally copyin the - * msg.msg_control and msg.msg_name fields. */ int sendmsg(struct sendmsg_args *uap) { + struct thread *td = curthread; struct msghdr msg; - struct iovec aiov[UIO_SMALLIOV], *iov = NULL; + struct uio auio; + struct iovec aiov[UIO_SMALLIOV], *iov = NULL, *iovp; struct sockaddr *sa = NULL; struct mbuf *control = NULL; - int error; + int error, i; error = copyin(uap->msg, (caddr_t)&msg, sizeof(msg)); if (error) @@ -651,11 +631,10 @@ error = getsockaddr(&sa, msg.msg_name, msg.msg_namelen); if (error) return (error); - msg.msg_name = sa; } /* - * We always copyin msg.msg_iov. + * Populate auio. */ if (msg.msg_iovlen >= UIO_MAXIOV) { error = EMSGSIZE; @@ -667,31 +646,49 @@ } else { iov = aiov; } - error = copyin(msg.msg_iov, iov, - msg.msg_iovlen * sizeof(struct iovec)); + error = copyin(msg.msg_iov, iov, msg.msg_iovlen * sizeof(struct iovec)); if (error) goto cleanup; - msg.msg_iov = iov; + auio.uio_iov = iov; + auio.uio_iovcnt = msg.msg_iovlen; + auio.uio_offset = 0; + auio.uio_resid = 0; + for (i = 0, iovp = auio.uio_iov; i < msg.msg_iovlen; i++, iovp++) { + auio.uio_resid += iovp->iov_len; + if (auio.uio_resid < 0) { + error = EINVAL; + goto cleanup; + } + } + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_WRITE; + auio.uio_td = td; /* * Conditionally copyin msg.msg_control. */ if (msg.msg_control) { - if (msg.msg_controllen < sizeof(struct cmsghdr)) { + if (msg.msg_controllen < sizeof(struct cmsghdr) || + msg.msg_controllen > MLEN) { error = EINVAL; goto cleanup; } - error = sockargs(&control, msg.msg_control, - msg.msg_controllen, MT_CONTROL); - if (error) + control = m_get(M_WAIT, MT_CONTROL); + if (control == NULL) { + error = ENOBUFS; + goto cleanup; + } + control->m_len = msg.msg_controllen; + error = copyin(msg.msg_control, mtod(control, caddr_t), + msg.msg_controllen); + if (error) { + m_free(control); goto cleanup; - msg.msg_control = control; + } } - /* Don't forget the flags. */ - msg.msg_flags = uap->flags; - - error = kern_sendmsg(uap->s, &msg, &uap->sysmsg_result); + error = kern_sendmsg(uap->s, sa, &auio, control, uap->flags, + &uap->sysmsg_result); cleanup: if (sa) @@ -702,20 +699,17 @@ } /* - * If mp->msg_namelen is non-zero, then when we return mp->msg_name is - * a pointer to the address that we recieved from. If it is zero, - * the address is freed before return. Don't forget to FREE() - * mp->msg_name if mp->msg_namelen is non-zero. + * kern_recvmsg() takes a handle to sa and control. If the handle is non- + * null, it returns a dynamically allocated struct sockaddr and an mbuf. + * Don't forget to FREE() and m_free() these if they are returned. */ int -kern_recvmsg(int s, struct msghdr *mp, int *res) +kern_recvmsg(int s, struct sockaddr **sa, struct uio *auio, + struct mbuf **control, int *flags, int *res) { struct thread *td = curthread; struct proc *p = td->td_proc; struct file *fp; - struct uio auio; - struct iovec *iov; - int i; int len, error; struct socket *so; #ifdef KTRACE @@ -726,38 +720,21 @@ error = holdsock(p->p_fd, s, &fp); if (error) return (error); - auio.uio_iov = mp->msg_iov; - auio.uio_iovcnt = mp->msg_iovlen; - auio.uio_segflg = UIO_USERSPACE; - auio.uio_rw = UIO_READ; - auio.uio_td = td; - auio.uio_offset = 0; /* XXX */ - auio.uio_resid = 0; - iov = mp->msg_iov; - for (i = 0; i < mp->msg_iovlen; i++, iov++) { - if ((auio.uio_resid += iov->iov_len) < 0) { - fdrop(fp, td); - return (EINVAL); - } - } #ifdef KTRACE if (KTRPOINT(td, KTR_GENIO)) { - int iovlen = auio.uio_iovcnt * sizeof (struct iovec); + int iovlen = auio->uio_iovcnt * sizeof (struct iovec); MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); - bcopy(auio.uio_iov, ktriov, iovlen); - ktruio = auio; + bcopy(auio->uio_iov, ktriov, iovlen); + ktruio = *auio; } #endif - len = auio.uio_resid; + len = auio->uio_resid; so = (struct socket *)fp->f_data; - error = so->so_proto->pr_usrreqs->pru_soreceive(so, - mp->msg_namelen ? (struct sockaddr **)&mp->msg_name : NULL, - &auio, NULL, - mp->msg_controllen ? (struct mbuf **)&mp->msg_control : NULL, - &mp->msg_flags); + error = so->so_proto->pr_usrreqs->pru_soreceive(so, sa, auio, NULL, + control, flags); if (error) { - if (auio.uio_resid != len && (error == ERESTART || + if (auio->uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; } @@ -765,14 +742,14 @@ if (ktriov != NULL) { if (error == 0) { ktruio.uio_iov = ktriov; - ktruio.uio_resid = len - auio.uio_resid; + ktruio.uio_resid = len - auio->uio_resid; ktrgenio(p->p_tracep, s, UIO_READ, &ktruio, error); } FREE(ktriov, M_TEMP); } #endif if (error == 0) - *res = len - auio.uio_resid; + *res = len - auio->uio_resid; fdrop(fp, td); return (error); } @@ -784,39 +761,43 @@ int recvfrom(struct recvfrom_args *uap) { - struct msghdr msg; + struct thread *td = curthread; + struct uio auio; struct iovec aiov; + struct sockaddr *sa = NULL; int error, fromlen; - if (uap->fromlenaddr) { + if (uap->from && uap->fromlenaddr) { error = copyin(uap->fromlenaddr, &fromlen, sizeof(fromlen)); if (error) return (error); + if (fromlen < 0) + return (EINVAL); } else { fromlen = 0; } - - msg.msg_name = NULL; - msg.msg_namelen = fromlen; - msg.msg_iov = &aiov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_flags = uap->flags; aiov.iov_base = uap->buf; aiov.iov_len = uap->len; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_offset = 0; + auio.uio_resid = uap->len; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_READ; + auio.uio_td = td; - error = kern_recvmsg(uap->s, &msg, &uap->sysmsg_result); + error = kern_recvmsg(uap->s, uap->from ? &sa : NULL, &auio, NULL, + &uap->flags, &uap->sysmsg_result); - fromlen = MIN(msg.msg_namelen, fromlen); - if (uap->from) { - if (error == 0) - error = copyout(msg.msg_name, uap->from, fromlen); + if (error == 0 && uap->from) { + fromlen = MIN(fromlen, sa->sa_len); + error = copyout(sa, uap->from, fromlen); if (error == 0) error = copyout(&fromlen, uap->fromlenaddr, sizeof(fromlen)); } - if (msg.msg_name) - FREE(msg.msg_name, M_SONAME); + if (sa) + FREE(sa, M_SONAME); return (error); } @@ -827,13 +808,15 @@ int recvmsg(struct recvmsg_args *uap) { + struct thread *td = curthread; struct msghdr msg; - struct iovec aiov[UIO_SMALLIOV], *iov = NULL; - struct mbuf *m, *ucontrol; - struct sockaddr *uname; + struct uio auio; + struct iovec aiov[UIO_SMALLIOV], *iov = NULL, *iovp; + struct mbuf *m, *control; + struct sockaddr *sa = NULL; caddr_t ctlbuf; - socklen_t *unamelenp, *ucontrollenp; - int error, fromlen, len; + socklen_t *ufromlenp, *ucontrollenp; + int error, fromlen, controllen, len, i, flags, *uflagsp; /* * This copyin handles everything except the iovec. @@ -842,20 +825,20 @@ if (error) return (error); - /* - * Save some userland pointers for the copyouts. - */ - uname = msg.msg_name; - unamelenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr, + if (msg.msg_name && msg.msg_namelen < 0) + return (EINVAL); + if (msg.msg_control && msg.msg_controllen < 0) + return (EINVAL); + + ufromlenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr, msg_namelen)); - ucontrol = msg.msg_control; ucontrollenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr, msg_controllen)); - - fromlen = msg.msg_namelen; + uflagsp = (int *)((caddr_t)uap->msg + offsetof(struct msghdr, + msg_flags)); /* - * Copyin msg.msg_iov. + * Populate auio. */ if (msg.msg_iovlen >= UIO_MAXIOV) return (EMSGSIZE); @@ -868,32 +851,44 @@ error = copyin(msg.msg_iov, iov, msg.msg_iovlen * sizeof(struct iovec)); if (error) goto cleanup; - msg.msg_iov = iov; + auio.uio_iov = iov; + auio.uio_iovcnt = msg.msg_iovlen; + auio.uio_offset = 0; + auio.uio_resid = 0; + for (i = 0, iovp = auio.uio_iov; i < msg.msg_iovlen; i++, iovp++) { + auio.uio_resid += iovp->iov_len; + if (auio.uio_resid < 0) { + error = EINVAL; + goto cleanup; + } + } + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_READ; + auio.uio_td = td; - /* Don't forget the flags. */ - msg.msg_flags = uap->flags; + flags = msg.msg_flags; - error = kern_recvmsg(uap->s, &msg, &uap->sysmsg_result); + error = kern_recvmsg(uap->s, msg.msg_name ? &sa : NULL, &auio, + msg.msg_control ? &control : NULL, &flags, &uap->sysmsg_result); /* - * Copyout msg.msg_name and msg.msg_namelen. + * Conditionally copyout the name and populate the namelen field. */ - if (error == 0 && uname) { - fromlen = MIN(msg.msg_namelen, fromlen); - error = copyout(msg.msg_name, uname, fromlen); + if (error == 0 && msg.msg_name) { + fromlen = MIN(msg.msg_namelen, sa->sa_len); + error = copyout(sa, msg.msg_name, fromlen); if (error == 0) - error = copyout(&fromlen, unamelenp, - sizeof(*unamelenp)); + error = copyout(&fromlen, ufromlenp, + sizeof(*ufromlenp)); } /* * Copyout msg.msg_control and msg.msg_controllen. */ - if (error == 0 && ucontrol) { + if (error == 0 && msg.msg_control) { len = msg.msg_controllen; - msg.msg_controllen = 0; - m = msg.msg_control; - ctlbuf = (caddr_t)ucontrol; + m = control; + ctlbuf = (caddr_t)msg.msg_control; while(m && len > 0) { unsigned int tocopy; @@ -913,18 +908,21 @@ len -= tocopy; m = m->m_next; } - msg.msg_controllen = ctlbuf - (caddr_t)ucontrol; - error = copyout(&msg.msg_controllen, ucontrollenp, + controllen = ctlbuf - (caddr_t)msg.msg_control; + error = copyout(&controllen, ucontrollenp, sizeof(*ucontrollenp)); } + if (error == 0) + error = copyout(&flags, uflagsp, sizeof(*uflagsp)); + cleanup: - if (msg.msg_name) - FREE(msg.msg_name, M_SONAME); + if (sa) + FREE(sa, M_SONAME); if (iov != aiov) FREE(iov, M_IOV); - if (msg.msg_control) - m_freem(msg.msg_control); + if (control) + m_freem(control); return (error); } @@ -1191,6 +1189,10 @@ return (error); } +/* + * sockargs() will be removed soon. It is currently only called from the + * emulation code. + */ int sockargs(mp, buf, buflen, type) struct mbuf **mp; Index: emulation/43bsd/43bsd_socket.c =================================================================== RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/emulation/43bsd/43bsd_socket.c,v retrieving revision 1.2 diff -u -u -r1.2 43bsd_socket.c --- emulation/43bsd/43bsd_socket.c 19 Sep 2003 08:02:27 -0000 1.2 +++ emulation/43bsd/43bsd_socket.c 2 Oct 2003 09:11:02 -0000 @@ -46,9 +46,10 @@ #include #include #include +#include #include #include -#include +#include #include #include #include @@ -179,20 +180,23 @@ int osend(struct osend_args *uap) { - struct msghdr msg; + struct thread *td = curthread; + struct uio auio; struct iovec aiov; int error; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = &aiov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_flags = 0; aiov.iov_base = uap->buf; aiov.iov_len = uap->len; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_offset = 0; + auio.uio_resid = uap->len; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_WRITE; + auio.uio_td = td; - error = kern_sendmsg(uap->s, &msg, &uap->sysmsg_result); + error = kern_sendmsg(uap->s, NULL, &auio, NULL, uap->flags, + &uap->sysmsg_result); return (error); } @@ -200,12 +204,14 @@ int osendmsg(struct osendmsg_args *uap) { + struct thread *td = curthread; struct msghdr msg; - struct iovec aiov[UIO_SMALLIOV], *iov = NULL; + struct uio auio; + struct iovec aiov[UIO_SMALLIOV], *iov = NULL, *iovp; struct sockaddr *sa = NULL; struct mbuf *control = NULL; struct cmsghdr *cm; - int error; + int error, i; error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg)); if (error) @@ -219,21 +225,60 @@ msg.msg_namelen); if (error) return (error); - msg.msg_name = sa; } /* + * Populate auio. + */ + if (msg.msg_iovlen >= UIO_MAXIOV) { + error = EMSGSIZE; + goto cleanup; + } + if (msg.msg_iovlen >= UIO_SMALLIOV) { + MALLOC(iov, struct iovec *, + sizeof(struct iovec) * msg.msg_iovlen, M_IOV, + M_WAITOK); + } else { + iov = aiov; + } + error = copyin(msg.msg_iov, iov, msg.msg_iovlen * sizeof(struct iovec)); + if (error) + goto cleanup; + auio.uio_iov = iov; + auio.uio_iovcnt = msg.msg_iovlen; + auio.uio_offset = 0; + auio.uio_resid = 0; + for (i = 0, iovp = auio.uio_iov; i < msg.msg_iovlen; i++, iovp++) { + auio.uio_resid += iovp->iov_len; + if (auio.uio_resid < 0) { + error = EINVAL; + goto cleanup; + } + } + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_WRITE; + auio.uio_td = td; + + /* * Conditionally copyin msg.msg_control. */ if (msg.msg_control) { - if (msg.msg_controllen < sizeof(struct cmsghdr)) { + if (msg.msg_controllen < 0 || msg.msg_controllen > MLEN) { error = EINVAL; goto cleanup; } - error = sockargs(&control, msg.msg_control, - msg.msg_controllen, MT_CONTROL); - if (error) + control = m_get(M_WAIT, MT_CONTROL); + if (control == NULL) { + error = ENOBUFS; goto cleanup; + } + control->m_len = msg.msg_controllen; + error = copyin(msg.msg_control, mtod(control, caddr_t), + msg.msg_controllen); + if (error) { + m_free(control); + goto cleanup; + } /* * In 4.3BSD, the only type of ancillary data was * access rights and this data did not use a header @@ -251,30 +296,10 @@ cm->cmsg_level = SOL_SOCKET; cm->cmsg_type = SCM_RIGHTS; } - msg.msg_control = control; } - /* - * We always copyin msg.msg_iov. - */ - if (msg.msg_iovlen >= UIO_MAXIOV) { - error = EMSGSIZE; - goto cleanup; - } - if (msg.msg_iovlen >= UIO_SMALLIOV) { - MALLOC(iov, struct iovec *, - sizeof(struct iovec) * msg.msg_iovlen, M_IOV, - M_WAITOK); - } else { - iov = aiov; - } - error = copyin(msg.msg_iov, iov, - msg.msg_iovlen * sizeof (struct iovec)); - if (error) - goto cleanup; - msg.msg_iov = iov; - - error = kern_sendmsg(uap->s, &msg, &uap->sysmsg_result); + error = kern_sendmsg(uap->s, sa, &auio, control, uap->flags, + &uap->sysmsg_result); cleanup: if (sa) @@ -287,20 +312,23 @@ int orecv(struct orecv_args *uap) { - struct msghdr msg; + struct thread *td = curthread; + struct uio auio; struct iovec aiov; int error; - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = &aiov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_flags = uap->flags; aiov.iov_base = uap->buf; aiov.iov_len = uap->len; + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_offset = 0; + auio.uio_resid = uap->len; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_READ; + auio.uio_td = td; - error = kern_recvmsg(uap->s, &msg, &uap->sysmsg_result); + error = kern_recvmsg(uap->s, NULL, &auio, NULL, &uap->flags, + &uap->sysmsg_result); return (error); } @@ -308,34 +336,37 @@ int orecvfrom(struct recvfrom_args *uap) { - struct msghdr msg; + struct thread *td = curthread; + struct uio auio; struct iovec aiov; + struct sockaddr *sa = NULL; int error, fromlen; - if (uap->fromlenaddr) { + if (uap->from && uap->fromlenaddr) { error = copyin(uap->fromlenaddr, &fromlen, sizeof(fromlen)); if (error) return (error); + if (fromlen < 0) + return (EINVAL); } else { fromlen = 0; } - - msg.msg_name = NULL; - msg.msg_namelen = fromlen; - msg.msg_iov = &aiov; - msg.msg_iovlen = 1; - msg.msg_control = NULL; - msg.msg_flags = uap->flags; aiov.iov_base = uap->buf; aiov.iov_len = uap->len; - - error = kern_recvmsg(uap->s, &msg, &uap->sysmsg_result); - - fromlen = MIN(msg.msg_namelen, fromlen); - if (uap->from) { - if (error == 0) - error = compat_43_copyout_sockaddr(msg.msg_name, - uap->from, fromlen); + auio.uio_iov = &aiov; + auio.uio_iovcnt = 1; + auio.uio_offset = 0; + auio.uio_resid = uap->len; + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_READ; + auio.uio_td = td; + + error = kern_recvmsg(uap->s, uap->from ? &sa : NULL, &auio, NULL, + &uap->flags, &uap->sysmsg_result); + + if (error == 0 && uap->from) { + fromlen = MIN(fromlen, sa->sa_len); + error = compat_43_copyout_sockaddr(sa, uap->from, fromlen); if (error == 0) /* * Old recvfrom didn't signal an error if this @@ -343,8 +374,8 @@ */ copyout(&fromlen, uap->fromlenaddr, sizeof(fromlen)); } - if (msg.msg_name) - FREE(msg.msg_name, M_SONAME); + if (sa) + FREE(sa, M_SONAME); return (error); } @@ -352,13 +383,15 @@ int orecvmsg(struct orecvmsg_args *uap) { + struct thread *td = curthread; struct msghdr msg; - struct iovec aiov[UIO_SMALLIOV], *iov = NULL; - struct mbuf *m, *ucontrol; - caddr_t uname; + struct uio auio; + struct iovec aiov[UIO_SMALLIOV], *iov = NULL, *iovp; + struct mbuf *m, *control; + struct sockaddr *sa = NULL; caddr_t ctlbuf; - socklen_t *unamelenp, *ucontrollenp; - int error, fromlen, len; + socklen_t *ufromlenp, *ucontrollenp; + int error, fromlen, controllen, len, i, flags, *uflagsp; /* * This copyin handles everything except the iovec. @@ -367,20 +400,20 @@ if (error) return (error); - /* - * Save some userland pointers for the copyouts. - */ - uname = msg.msg_name; - unamelenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr, + if (msg.msg_name && msg.msg_namelen < 0) + return (EINVAL); + if (msg.msg_control && msg.msg_controllen < 0) + return (EINVAL); + + ufromlenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr, msg_namelen)); - ucontrol = msg.msg_control; ucontrollenp = (socklen_t *)((caddr_t)uap->msg + offsetof(struct msghdr, msg_controllen)); - - fromlen = msg.msg_namelen; + uflagsp = (int *)((caddr_t)uap->msg + offsetof(struct msghdr, + msg_flags)); /* - * Copyin msg.msg_iov. + * Populate auio. */ if (msg.msg_iovlen >= UIO_MAXIOV) return (EMSGSIZE); @@ -393,56 +426,65 @@ error = copyin(msg.msg_iov, iov, msg.msg_iovlen * sizeof(struct iovec)); if (error) goto cleanup; - msg.msg_iov = iov; + auio.uio_iov = iov; + auio.uio_iovcnt = msg.msg_iovlen; + auio.uio_offset = 0; + auio.uio_resid = 0; + for (i = 0, iovp = auio.uio_iov; i < msg.msg_iovlen; i++, iovp++) { + auio.uio_resid += iovp->iov_len; + if (auio.uio_resid < 0) { + error = EINVAL; + goto cleanup; + } + } + auio.uio_segflg = UIO_USERSPACE; + auio.uio_rw = UIO_READ; + auio.uio_td = td; - /* Don't forget the flags. */ - msg.msg_flags = uap->flags; + flags = msg.msg_flags; - error = kern_recvmsg(uap->s, &msg, &uap->sysmsg_result); + error = kern_recvmsg(uap->s, msg.msg_name ? &sa : NULL, &auio, + msg.msg_control ? &control : NULL, &flags, &uap->sysmsg_result); /* * Copyout msg.msg_name and msg.msg_namelen. */ - if (error == 0 && uname) { - fromlen = MIN(msg.msg_namelen, fromlen); - error = compat_43_copyout_sockaddr(msg.msg_name, uname, - fromlen); + if (error == 0 && msg.msg_name) { + fromlen = MIN(msg.msg_namelen, sa->sa_len); + error = compat_43_copyout_sockaddr(sa, msg.msg_name, fromlen); if (error == 0) /* * Old recvfrom didn't signal an error if this * next copyout failed. */ - copyout(&fromlen, unamelenp, sizeof(*unamelenp)); + copyout(&fromlen, ufromlenp, sizeof(*ufromlenp)); } /* * Copyout msg.msg_control and msg.msg_controllen. */ - if (error == 0 && ucontrol) { + if (error == 0 && msg.msg_control) { /* * If we receive access rights, trim the cmsghdr; anything * else is tossed. */ - if (msg.msg_control) { - if (mtod((struct mbuf *)msg.msg_control, - struct cmsghdr *)->cmsg_level != SOL_SOCKET || - mtod((struct mbuf *)msg.msg_control, - struct cmsghdr *)->cmsg_type != SCM_RIGHTS) { - int temp = 0; - error = copyout(&temp, ucontrollenp, - sizeof(*ucontrollenp)); - goto cleanup; - } - ((struct mbuf *)msg.msg_control)->m_len -= - sizeof(struct cmsghdr); - ((struct mbuf *)msg.msg_control)->m_data += - sizeof(struct cmsghdr); + if (mtod((struct mbuf *)msg.msg_control, + struct cmsghdr *)->cmsg_level != SOL_SOCKET || + mtod((struct mbuf *)msg.msg_control, + struct cmsghdr *)->cmsg_type != SCM_RIGHTS) { + int temp = 0; + error = copyout(&temp, ucontrollenp, + sizeof(*ucontrollenp)); + goto cleanup; } + ((struct mbuf *)msg.msg_control)->m_len -= + sizeof(struct cmsghdr); + ((struct mbuf *)msg.msg_control)->m_data += + sizeof(struct cmsghdr); len = msg.msg_controllen; - msg.msg_controllen = 0; - m = msg.msg_control; - ctlbuf = (caddr_t)ucontrol; + m = control; + ctlbuf = (caddr_t)msg.msg_control; while(m && len > 0) { unsigned int tocopy; @@ -463,18 +505,21 @@ len -= tocopy; m = m->m_next; } - msg.msg_controllen = ctlbuf - (caddr_t)ucontrol; - error = copyout(&msg.msg_controllen, ucontrollenp, + controllen = ctlbuf - (caddr_t)msg.msg_control; + error = copyout(&controllen, ucontrollenp, sizeof(*ucontrollenp)); } + if (error == 0) + error = copyout(&flags, uflagsp, sizeof(*uflagsp)); + cleanup: - if (msg.msg_name) - FREE(msg.msg_name, M_SONAME); + if (sa) + FREE(sa, M_SONAME); if (iov != aiov) FREE(iov, M_IOV); - if (msg.msg_control) - m_freem(msg.msg_control); + if (control) + m_freem(control); return (error); } Index: sys/socket.h =================================================================== RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/sys/socket.h,v retrieving revision 1.5 diff -u -u -r1.5 socket.h --- sys/socket.h 19 Sep 2003 08:02:27 -0000 1.5 +++ sys/socket.h 30 Sep 2003 12:14:22 -0000 @@ -327,7 +327,6 @@ #define MSG_WAITALL 0x40 /* wait for full request or error */ #define MSG_DONTWAIT 0x80 /* this message should be nonblocking */ #define MSG_EOF 0x100 /* data completes connection */ -#define MSG_COMPAT 0x8000 /* used in sendit() */ /* * Header for ancillary data objects in msg_control buffer. Index: sys/kern_syscall.h =================================================================== RCS file: /nfs/daver/cvs-repos/cvs-dragonflybsd/src/sys/sys/kern_syscall.h,v retrieving revision 1.3 diff -u -u -r1.3 kern_syscall.h --- sys/kern_syscall.h 29 Sep 2003 05:34:08 -0000 1.3 +++ sys/kern_syscall.h 30 Sep 2003 08:29:55 -0000 @@ -31,8 +31,9 @@ #ifndef _SYS_KERN_SYSCALL_H_ #define _SYS_KERN_SYSCALL_H_ -struct sockaddr; +struct mbuf; struct msghdr; +struct sockaddr; struct sockopt; int kern_accept(int s, struct sockaddr **name, int *namelen, int *res); @@ -42,8 +43,10 @@ int kern_getpeername(int s, struct sockaddr **name, int *namelen); int kern_getsockopt(int s, struct sockopt *sopt); int kern_getsockname(int s, struct sockaddr **name, int *namelen); -int kern_recvmsg(int s, struct msghdr *mp, int *res); -int kern_sendmsg(int s, struct msghdr *mp, int *res); +int kern_recvmsg(int s, struct sockaddr **sa, struct uio *auio, + struct mbuf **control, int *flags, int *res); +int kern_sendmsg(int s, struct sockaddr *sa, struct uio *auio, + struct mbuf *control, int flags, int *res); int kern_setsockopt(int s, struct sockopt *sopt); int kern_socketpair(int domain, int type, int protocol, int *sockv);