diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index 465c5737d177..c73a57a87fd7 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -993,35 +993,22 @@ linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args) { struct linux_sendmsg_args linux_args; struct msghdr msg; - struct iovec aiov[UIO_SMALLIOV], *iov; + struct iovec *iov; int error; - if ((error = copyin(args, &linux_args, sizeof(linux_args)))) + error = copyin(args, &linux_args, sizeof(linux_args)); + if (error) return (error); - error = copyin(linux_args.msg, &msg, sizeof(msg)); if (error) return (error); - if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { - if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) - return (EMSGSIZE); - MALLOC(iov, struct iovec *, - sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, - M_WAITOK); - } else { - iov = aiov; - } - if (msg.msg_iovlen && - (error = copyin(msg.msg_iov, iov, - (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))) - goto done; + error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); + if (error) + return (error); msg.msg_iov = iov; msg.msg_flags = 0; - error = linux_sendit(td, linux_args.s, &msg, linux_args.flags); -done: - if (iov != aiov) - FREE(iov, M_IOV); + free(iov, M_IOV); return (error); } diff --git a/sys/compat/svr4/svr4_stream.c b/sys/compat/svr4/svr4_stream.c index 853a2722aa8c..d91c185c33a8 100644 --- a/sys/compat/svr4/svr4_stream.c +++ b/sys/compat/svr4/svr4_stream.c @@ -163,8 +163,7 @@ svr4_sendit(td, s, mp, flags) int len, error; struct socket *so; #ifdef KTRACE - struct iovec *ktriov = NULL; - struct uio ktruio; + struct uio *ktruio = NULL; #endif if ((error = fgetsock(td, s, &so, NULL)) != 0) @@ -212,13 +211,8 @@ svr4_sendit(td, s, mp, flags) control = 0; } #ifdef KTRACE - if (KTRPOINT(td, KTR_GENIO)) { - 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; - } + if (KTRPOINT(td, KTR_GENIO)) + ktruio = cloneuio(&auio); #endif len = auio.uio_resid; error = so->so_proto->pr_usrreqs->pru_sosend(so, to, &auio, 0, control, @@ -236,13 +230,9 @@ svr4_sendit(td, s, mp, flags) if (error == 0) td->td_retval[0] = len - auio.uio_resid; #ifdef KTRACE - if (ktriov != NULL) { - if (error == 0) { - ktruio.uio_iov = ktriov; - ktruio.uio_resid = td->td_retval[0]; - ktrgenio(s, UIO_WRITE, &ktruio, error); - } - FREE(ktriov, M_TEMP); + if (ktruio != NULL) { + ktruio->uio_resid = td->td_retval[0]; + ktrgenio(s, UIO_WRITE, ktruio, error); } #endif bad: @@ -269,8 +259,7 @@ svr4_recvit(td, s, mp, namelenp) struct socket *so; struct sockaddr *fromsa = 0; #ifdef KTRACE - struct iovec *ktriov = NULL; - struct uio ktruio; + struct uio *ktruio = NULL; #endif if ((error = fgetsock(td, s, &so, NULL)) != 0) @@ -299,13 +288,8 @@ svr4_recvit(td, s, mp, namelenp) } } #ifdef KTRACE - if (KTRPOINT(td, KTR_GENIO)) { - 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; - } + if (KTRPOINT(td, KTR_GENIO)) + ktruio = cloneuio(&auio); #endif len = auio.uio_resid; error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio, @@ -317,13 +301,9 @@ svr4_recvit(td, s, mp, namelenp) error = 0; } #ifdef KTRACE - if (ktriov != NULL) { - if (error == 0) { - ktruio.uio_iov = ktriov; - ktruio.uio_resid = len - auio.uio_resid; - ktrgenio(s, UIO_READ, &ktruio, error); - } - FREE(ktriov, M_TEMP); + if (ktruio != NULL) { + ktruio->uio_resid = len - auio.uio_resid; + ktrgenio(s, UIO_READ, ktruio, error); } #endif if (error) diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index 8a2b0a512f09..694634a91023 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -413,13 +413,17 @@ ktrgenio(fd, rw, uio, error) int datalen; char *buf; - if (error) + if (error) { + free(uio, M_IOV); return; + } uio->uio_offset = 0; uio->uio_rw = UIO_WRITE; datalen = imin(uio->uio_resid, ktr_geniosize); buf = malloc(datalen, M_KTRACE, M_WAITOK); - if (uiomove(buf, datalen, uio)) { + error = uiomove(buf, datalen, uio); + free(uio, M_IOV); + if (error) { free(buf, M_KTRACE); return; } diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c index 7ccccddf6739..8d5c6f07d9e7 100644 --- a/sys/kern/kern_subr.c +++ b/sys/kern/kern_subr.c @@ -474,40 +474,69 @@ copyinstrfrom(const void * __restrict src, void * __restrict dst, size_t len, } int -uiofromiov(struct iovec *iovp, u_int iovcnt, struct uio *uio) +copyiniov(struct iovec *iovp, u_int iovcnt, struct iovec **iov, int error) +{ + u_int iovlen; + + *iov = NULL; + if (iovcnt > UIO_MAXIOV) + return (error); + iovlen = iovcnt * sizeof (struct iovec); + *iov = malloc(iovlen, M_IOV, M_WAITOK); + error = copyin(iovp, *iov, iovlen); + if (error) { + free(*iov, M_IOV); + *iov = NULL; + } + return (error); +} + +int +copyinuio(struct iovec *iovp, u_int iovcnt, struct uio **uiop) { struct iovec *iov; + struct uio *uio; u_int iovlen; int error, i; - /* note: can't use iovlen until iovcnt is validated */ + *uiop = NULL; + if (iovcnt > UIO_MAXIOV) + return (EINVAL); iovlen = iovcnt * sizeof (struct iovec); - if (iovcnt > UIO_MAXIOV) { - error = EINVAL; - goto done; + uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); + iov = (struct iovec *)(uio + 1); + error = copyin(iovp, iov, iovlen); + if (error) { + free(uio, M_IOV); + return (error); } - MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); uio->uio_iov = iov; uio->uio_iovcnt = iovcnt; uio->uio_segflg = UIO_USERSPACE; uio->uio_offset = -1; - if ((error = copyin(iovp, iov, iovlen))) - goto done; uio->uio_resid = 0; for (i = 0; i < iovcnt; i++) { if (iov->iov_len > INT_MAX - uio->uio_resid) { - error = EINVAL; - goto done; + free(uio, M_IOV); + return (EINVAL); } uio->uio_resid += iov->iov_len; iov++; } - -done: - if (error && uio->uio_iov) { - FREE(uio->uio_iov, M_IOV); - uio->uio_iov = NULL; - } - return (error); - + *uiop = uio; + return (0); +} + +struct uio * +cloneuio(struct uio *uiop) +{ + struct uio *uio; + int iovlen; + + iovlen = uiop->uio_iovcnt * sizeof (struct iovec); + uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK); + *uio = *uiop; + uio->uio_iov = (struct iovec *)(uio + 1); + bcopy(uiop->uio_iov, uio->uio_iov, iovlen); + return (uio); } diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c index 9f4bedd75eab..3650ca1ff45b 100644 --- a/sys/kern/subr_prf.c +++ b/sys/kern/subr_prf.c @@ -243,9 +243,7 @@ log(int level, const char *fmt, ...) void log_console(struct uio *uio) { - int c, i, error, iovlen, nl; - struct uio muio; - struct iovec *miov = NULL; + int c, i, error, nl; char *consbuffer; int pri; @@ -253,13 +251,8 @@ log_console(struct uio *uio) return; pri = LOG_INFO | LOG_CONSOLE; - muio = *uio; - iovlen = uio->uio_iovcnt * sizeof (struct iovec); - MALLOC(miov, struct iovec *, iovlen, M_TEMP, M_WAITOK); - MALLOC(consbuffer, char *, CONSCHUNK, M_TEMP, M_WAITOK); - bcopy(muio.uio_iov, miov, iovlen); - muio.uio_iov = miov; - uio = &muio; + uio = cloneuio(uio); + consbuffer = malloc(CONSCHUNK, M_TEMP, M_WAITOK); nl = 0; while (uio->uio_resid > 0) { @@ -278,8 +271,8 @@ log_console(struct uio *uio) if (!nl) msglogchar('\n', pri); msgbuftrigger = 1; - FREE(miov, M_TEMP); - FREE(consbuffer, M_TEMP); + free(uio, M_IOV); + free(consbuffer, M_TEMP); return; } diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index ab48888f76ad..13b5125847c4 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -164,9 +164,7 @@ dofileread(td, fp, fd, buf, nbyte, offset, flags) struct iovec aiov; long cnt, error = 0; #ifdef KTRACE - struct iovec ktriov; - struct uio ktruio; - int didktr = 0; + struct uio *ktruio = NULL; #endif aiov.iov_base = buf; @@ -181,14 +179,8 @@ dofileread(td, fp, fd, buf, nbyte, offset, flags) auio.uio_segflg = UIO_USERSPACE; auio.uio_td = td; #ifdef KTRACE - /* - * if tracing, save a copy of iovec - */ - if (KTRPOINT(td, KTR_GENIO)) { - ktriov = aiov; - ktruio = auio; - didktr = 1; - } + if (KTRPOINT(td, KTR_GENIO)) + ktruio = cloneuio(&auio); #endif cnt = nbyte; @@ -199,10 +191,9 @@ dofileread(td, fp, fd, buf, nbyte, offset, flags) } cnt -= auio.uio_resid; #ifdef KTRACE - if (didktr && error == 0) { - ktruio.uio_iov = &ktriov; - ktruio.uio_resid = cnt; - ktrgenio(fd, UIO_READ, &ktruio, error); + if (ktruio != NULL) { + ktruio->uio_resid = cnt; + ktrgenio(fd, UIO_READ, ktruio, error); } #endif td->td_retval[0] = cnt; @@ -223,86 +214,46 @@ struct readv_args { * MPSAFE */ int -readv(td, uap) - struct thread *td; - struct readv_args *uap; +readv(struct thread *td, struct readv_args *uap) { struct file *fp; - struct uio auio; - struct iovec *iov; - struct iovec *needfree; - struct iovec aiov[UIO_SMALLIOV]; - long i, cnt; + struct uio *auio = NULL; + long cnt; int error; - u_int iovlen; #ifdef KTRACE - struct iovec *ktriov = NULL; - struct uio ktruio; + struct uio *ktruio = NULL; #endif - if ((error = fget_read(td, uap->fd, &fp)) != 0) + error = fget_read(td, uap->fd, &fp); + if (error) + return (error); + error = copyinuio(uap->iovp, uap->iovcnt, &auio); + if (error) { + fdrop(fp, td); return (error); - needfree = NULL; - /* note: can't use iovlen until iovcnt is validated */ - iovlen = uap->iovcnt * sizeof (struct iovec); - if (uap->iovcnt > UIO_SMALLIOV) { - if (uap->iovcnt > UIO_MAXIOV) { - error = EINVAL; - goto done; - } - MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); - needfree = iov; - } else - iov = aiov; - auio.uio_iov = iov; - auio.uio_iovcnt = uap->iovcnt; - auio.uio_rw = UIO_READ; - auio.uio_segflg = UIO_USERSPACE; - auio.uio_td = td; - auio.uio_offset = -1; - if ((error = copyin(uap->iovp, iov, iovlen))) - goto done; - auio.uio_resid = 0; - for (i = 0; i < uap->iovcnt; i++) { - if (iov->iov_len > INT_MAX - auio.uio_resid) { - error = EINVAL; - goto done; - } - auio.uio_resid += iov->iov_len; - iov++; } + auio->uio_rw = UIO_READ; + auio->uio_td = td; #ifdef KTRACE - /* - * if tracing, save a copy of iovec - */ - if (KTRPOINT(td, KTR_GENIO)) { - MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); - bcopy(auio.uio_iov, ktriov, iovlen); - ktruio = auio; - } + if (KTRPOINT(td, KTR_GENIO)) + ktruio = cloneuio(auio); #endif - cnt = auio.uio_resid; - if ((error = fo_read(fp, &auio, td->td_ucred, 0, td))) { - if (auio.uio_resid != cnt && (error == ERESTART || + cnt = auio->uio_resid; + if ((error = fo_read(fp, auio, td->td_ucred, 0, td))) { + if (auio->uio_resid != cnt && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; } - cnt -= auio.uio_resid; + cnt -= auio->uio_resid; #ifdef KTRACE - if (ktriov != NULL) { - if (error == 0) { - ktruio.uio_iov = ktriov; - ktruio.uio_resid = cnt; - ktrgenio(uap->fd, UIO_READ, &ktruio, error); - } - FREE(ktriov, M_TEMP); + if (ktruio != NULL) { + ktruio->uio_resid = cnt; + ktrgenio(uap->fd, UIO_READ, ktruio, error); } #endif td->td_retval[0] = cnt; -done: + free(auio, M_IOV); fdrop(fp, td); - if (needfree) - FREE(needfree, M_IOV); return (error); } @@ -389,9 +340,7 @@ dofilewrite(td, fp, fd, buf, nbyte, offset, flags) struct iovec aiov; long cnt, error = 0; #ifdef KTRACE - struct iovec ktriov; - struct uio ktruio; - int didktr = 0; + struct uio *ktruio = NULL; #endif aiov.iov_base = (void *)(uintptr_t)buf; @@ -406,14 +355,8 @@ dofilewrite(td, fp, fd, buf, nbyte, offset, flags) auio.uio_segflg = UIO_USERSPACE; auio.uio_td = td; #ifdef KTRACE - /* - * if tracing, save a copy of iovec and uio - */ - if (KTRPOINT(td, KTR_GENIO)) { - ktriov = aiov; - ktruio = auio; - didktr = 1; - } + if (KTRPOINT(td, KTR_GENIO)) + ktruio = cloneuio(&auio); #endif cnt = nbyte; if (fp->f_type == DTYPE_VNODE) @@ -431,10 +374,9 @@ dofilewrite(td, fp, fd, buf, nbyte, offset, flags) } cnt -= auio.uio_resid; #ifdef KTRACE - if (didktr && error == 0) { - ktruio.uio_iov = &ktriov; - ktruio.uio_resid = cnt; - ktrgenio(fd, UIO_WRITE, &ktruio, error); + if (ktruio != NULL) { + ktruio->uio_resid = cnt; + ktrgenio(fd, UIO_WRITE, ktruio, error); } #endif td->td_retval[0] = cnt; @@ -455,68 +397,35 @@ struct writev_args { * MPSAFE */ int -writev(td, uap) - struct thread *td; - register struct writev_args *uap; +writev(struct thread *td, struct writev_args *uap) { struct file *fp; - struct uio auio; - register struct iovec *iov; - struct iovec *needfree; - struct iovec aiov[UIO_SMALLIOV]; - long i, cnt, error = 0; - u_int iovlen; + struct uio *auio = NULL; + long cnt; + int error; #ifdef KTRACE - struct iovec *ktriov = NULL; - struct uio ktruio; + struct uio *ktruio = NULL; #endif - if ((error = fget_write(td, uap->fd, &fp)) != 0) + error = fget_write(td, uap->fd, &fp); + if (error) return (EBADF); - needfree = NULL; - /* note: can't use iovlen until iovcnt is validated */ - iovlen = uap->iovcnt * sizeof (struct iovec); - if (uap->iovcnt > UIO_SMALLIOV) { - if (uap->iovcnt > UIO_MAXIOV) { - error = EINVAL; - goto done; - } - MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); - needfree = iov; - } else - iov = aiov; - auio.uio_iov = iov; - auio.uio_iovcnt = uap->iovcnt; - auio.uio_rw = UIO_WRITE; - auio.uio_segflg = UIO_USERSPACE; - auio.uio_td = td; - auio.uio_offset = -1; - if ((error = copyin(uap->iovp, iov, iovlen))) - goto done; - auio.uio_resid = 0; - for (i = 0; i < uap->iovcnt; i++) { - if (iov->iov_len > INT_MAX - auio.uio_resid) { - error = EINVAL; - goto done; - } - auio.uio_resid += iov->iov_len; - iov++; + error = copyinuio(uap->iovp, uap->iovcnt, &auio); + if (error) { + fdrop(fp, td); + return (error); } + auio->uio_rw = UIO_WRITE; + auio->uio_td = td; #ifdef KTRACE - /* - * if tracing, save a copy of iovec and uio - */ - if (KTRPOINT(td, KTR_GENIO)) { - MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); - bcopy(auio.uio_iov, ktriov, iovlen); - ktruio = auio; - } + if (KTRPOINT(td, KTR_GENIO)) + ktruio = cloneuio(auio); #endif - cnt = auio.uio_resid; + cnt = auio->uio_resid; if (fp->f_type == DTYPE_VNODE) bwillwrite(); - if ((error = fo_write(fp, &auio, td->td_ucred, 0, td))) { - if (auio.uio_resid != cnt && (error == ERESTART || + if ((error = fo_write(fp, auio, td->td_ucred, 0, td))) { + if (auio->uio_resid != cnt && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; if (error == EPIPE) { @@ -525,22 +434,16 @@ writev(td, uap) PROC_UNLOCK(td->td_proc); } } - cnt -= auio.uio_resid; + cnt -= auio->uio_resid; #ifdef KTRACE - if (ktriov != NULL) { - if (error == 0) { - ktruio.uio_iov = ktriov; - ktruio.uio_resid = cnt; - ktrgenio(uap->fd, UIO_WRITE, &ktruio, error); - } - FREE(ktriov, M_TEMP); + if (ktruio != NULL) { + ktruio->uio_resid = cnt; + ktrgenio(uap->fd, UIO_WRITE, ktruio, error); } #endif td->td_retval[0] = cnt; -done: fdrop(fp, td); - if (needfree) - FREE(needfree, M_IOV); + free(auio, M_IOV); return (error); } diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 27440d4d9ea2..eeff60dd7e8b 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -701,9 +701,7 @@ kern_sendit(td, s, mp, flags, control) int i; int len, error; #ifdef KTRACE - struct iovec *ktriov = NULL; - struct uio ktruio; - int iovlen; + struct uio *ktruio = NULL; #endif NET_LOCK_GIANT(); @@ -733,12 +731,8 @@ kern_sendit(td, s, mp, flags, control) } } #ifdef KTRACE - if (KTRPOINT(td, KTR_GENIO)) { - iovlen = auio.uio_iovcnt * sizeof (struct iovec); - MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); - bcopy(auio.uio_iov, ktriov, iovlen); - ktruio = auio; - } + if (KTRPOINT(td, KTR_GENIO)) + ktruio = cloneuio(&auio); #endif len = auio.uio_resid; error = so->so_proto->pr_usrreqs->pru_sosend(so, mp->msg_name, &auio, @@ -757,13 +751,9 @@ kern_sendit(td, s, mp, flags, control) if (error == 0) td->td_retval[0] = len - auio.uio_resid; #ifdef KTRACE - if (ktriov != NULL) { - if (error == 0) { - ktruio.uio_iov = ktriov; - ktruio.uio_resid = td->td_retval[0]; - ktrgenio(s, UIO_WRITE, &ktruio, error); - } - FREE(ktriov, M_TEMP); + if (ktruio != NULL) { + ktruio->uio_resid = td->td_retval[0]; + ktrgenio(s, UIO_WRITE, ktruio, error); } #endif bad: @@ -842,41 +832,26 @@ osend(td, uap) int osendmsg(td, uap) struct thread *td; - register struct osendmsg_args /* { + struct osendmsg_args /* { int s; caddr_t msg; int flags; } */ *uap; { struct msghdr msg; - struct iovec aiov[UIO_SMALLIOV], *iov; + struct iovec *iov; int error; error = copyin(uap->msg, &msg, sizeof (struct omsghdr)); if (error) - goto done2; - if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { - if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) { - error = EMSGSIZE; - goto done2; - } - MALLOC(iov, struct iovec *, - sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, - M_WAITOK); - } else { - iov = aiov; - } - error = copyin(msg.msg_iov, iov, - (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); + return (error); + error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); if (error) - goto done; - msg.msg_flags = MSG_COMPAT; + return (error); msg.msg_iov = iov; + msg.msg_flags = MSG_COMPAT; error = sendit(td, uap->s, &msg, uap->flags); -done: - if (iov != aiov) - FREE(iov, M_IOV); -done2: + free(iov, M_IOV); return (error); } #endif @@ -887,56 +862,41 @@ osendmsg(td, uap) int sendmsg(td, uap) struct thread *td; - register struct sendmsg_args /* { + struct sendmsg_args /* { int s; caddr_t msg; int flags; } */ *uap; { struct msghdr msg; - struct iovec aiov[UIO_SMALLIOV], *iov; + struct iovec *iov; int error; error = copyin(uap->msg, &msg, sizeof (msg)); if (error) - goto done2; - if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { - if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) { - error = EMSGSIZE; - goto done2; - } - MALLOC(iov, struct iovec *, - sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, - M_WAITOK); - } else { - iov = aiov; - } - if (msg.msg_iovlen && - (error = copyin(msg.msg_iov, iov, - (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))) - goto done; + return (error); + error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); + if (error) + return (error); msg.msg_iov = iov; #ifdef COMPAT_OLDSOCK msg.msg_flags = 0; #endif error = sendit(td, uap->s, &msg, uap->flags); -done: - if (iov != aiov) - FREE(iov, M_IOV); -done2: + free(iov, M_IOV); return (error); } static int recvit(td, s, mp, namelenp) - register struct thread *td; + struct thread *td; int s; - register struct msghdr *mp; + struct msghdr *mp; void *namelenp; { struct uio auio; - register struct iovec *iov; - register int i; + struct iovec *iov; + int i; socklen_t len; int error; struct mbuf *m, *control = 0; @@ -944,9 +904,7 @@ recvit(td, s, mp, namelenp) struct socket *so; struct sockaddr *fromsa = 0; #ifdef KTRACE - struct iovec *ktriov = NULL; - struct uio ktruio; - int iovlen; + struct uio *ktruio = NULL; #endif NET_LOCK_GIANT(); @@ -982,12 +940,8 @@ recvit(td, s, mp, namelenp) } } #ifdef KTRACE - if (KTRPOINT(td, KTR_GENIO)) { - iovlen = auio.uio_iovcnt * sizeof (struct iovec); - MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); - bcopy(auio.uio_iov, ktriov, iovlen); - ktruio = auio; - } + if (KTRPOINT(td, KTR_GENIO)) + ktruio = cloneuio(&auio); #endif len = auio.uio_resid; error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio, @@ -999,13 +953,9 @@ recvit(td, s, mp, namelenp) error = 0; } #ifdef KTRACE - if (ktriov != NULL) { - if (error == 0) { - ktruio.uio_iov = ktriov; - ktruio.uio_resid = (int)len - auio.uio_resid; - ktrgenio(s, UIO_READ, &ktruio, error); - } - FREE(ktriov, M_TEMP); + if (ktruio != NULL) { + ktruio->uio_resid = (int)len - auio.uio_resid; + ktrgenio(s, UIO_READ, ktruio, error); } #endif if (error) @@ -1189,46 +1139,29 @@ orecv(td, uap) int orecvmsg(td, uap) struct thread *td; - register struct orecvmsg_args /* { + struct orecvmsg_args /* { int s; struct omsghdr *msg; int flags; } */ *uap; { struct msghdr msg; - struct iovec aiov[UIO_SMALLIOV], *iov; + struct iovec *iov; int error; error = copyin(uap->msg, &msg, sizeof (struct omsghdr)); if (error) return (error); - - if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { - if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) { - error = EMSGSIZE; - goto done2; - } - MALLOC(iov, struct iovec *, - sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, - M_WAITOK); - } else { - iov = aiov; - } - msg.msg_flags = uap->flags | MSG_COMPAT; - error = copyin(msg.msg_iov, iov, - (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); + error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); if (error) - goto done; + return (error); + msg.msg_flags = uap->flags | MSG_COMPAT; msg.msg_iov = iov; error = recvit(td, uap->s, &msg, &uap->msg->msg_namelen); - if (msg.msg_controllen && error == 0) error = copyout(&msg.msg_controllen, &uap->msg->msg_accrightslen, sizeof (int)); -done: - if (iov != aiov) - FREE(iov, M_IOV); -done2: + free(iov, M_IOV); return (error); } #endif @@ -1239,50 +1172,34 @@ orecvmsg(td, uap) int recvmsg(td, uap) struct thread *td; - register struct recvmsg_args /* { + struct recvmsg_args /* { int s; struct msghdr *msg; int flags; } */ *uap; { struct msghdr msg; - struct iovec aiov[UIO_SMALLIOV], *uiov, *iov; - register int error; + struct iovec *uiov, *iov; + int error; error = copyin(uap->msg, &msg, sizeof (msg)); if (error) - goto done2; - if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) { - if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) { - error = EMSGSIZE; - goto done2; - } - MALLOC(iov, struct iovec *, - sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV, - M_WAITOK); - } else { - iov = aiov; - } -#ifdef COMPAT_OLDSOCK - msg.msg_flags = uap->flags &~ MSG_COMPAT; -#else + return (error); + error = copyiniov(msg.msg_iov, msg.msg_iovlen, &iov, EMSGSIZE); + if (error) + return (error); msg.msg_flags = uap->flags; +#ifdef COMPAT_OLDSOCK + msg.msg_flags &= ~MSG_COMPAT; #endif uiov = msg.msg_iov; msg.msg_iov = iov; - error = copyin(uiov, iov, - (unsigned)(msg.msg_iovlen * sizeof (struct iovec))); - if (error) - goto done; error = recvit(td, uap->s, &msg, NULL); - if (!error) { + if (error == 0) { msg.msg_iov = uiov; error = copyout(&msg, uap->msg, sizeof(msg)); } -done: - if (iov != aiov) - FREE(iov, M_IOV); -done2: + free(iov, M_IOV); return (error); } @@ -1727,10 +1644,9 @@ do_sendfile(struct thread *td, struct sendfile_args *uap, int compat) struct vm_page *pg; struct writev_args nuap; struct sf_hdtr hdtr; - struct uio hdr_uio; + struct uio *hdr_uio = NULL; off_t off, xfsize, hdtr_size, sbytes = 0; int error, headersize = 0, headersent = 0; - struct iovec *hdr_iov = NULL; mtx_lock(&Giant); @@ -1783,16 +1699,13 @@ do_sendfile(struct thread *td, struct sendfile_args *uap, int compat) * Send any headers. */ if (hdtr.headers != NULL) { - hdr_uio.uio_td = td; - hdr_uio.uio_rw = UIO_WRITE; - error = uiofromiov(hdtr.headers, hdtr.hdr_cnt, - &hdr_uio); + error = copyinuio(hdtr.headers, hdtr.hdr_cnt, &hdr_uio); if (error) goto done; - /* Cache hdr_iov, m_uiotombuf may change it. */ - hdr_iov = hdr_uio.uio_iov; - if (hdr_uio.uio_resid > 0) { - m_header = m_uiotombuf(&hdr_uio, M_DONTWAIT, 0); + hdr_uio->uio_td = td; + hdr_uio->uio_rw = UIO_WRITE; + if (hdr_uio->uio_resid > 0) { + m_header = m_uiotombuf(hdr_uio, M_DONTWAIT, 0); if (m_header == NULL) goto done; headersize = m_header->m_pkthdr.len; @@ -2110,8 +2023,8 @@ do_sendfile(struct thread *td, struct sendfile_args *uap, int compat) vrele(vp); if (so) fputsock(so); - if (hdr_iov) - FREE(hdr_iov, M_IOV); + if (hdr_uio != NULL) + free(hdr_uio, M_IOV); if (m_header) m_freem(m_header); diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c index 22048f41b5fb..5252b3bc7cb3 100644 --- a/sys/kern/vfs_mount.c +++ b/sys/kern/vfs_mount.c @@ -376,46 +376,32 @@ nmount(td, uap) int flags; } */ *uap; { - struct uio auio; - struct iovec *iov, *needfree; - struct iovec aiov[UIO_SMALLIOV]; + struct uio *auio; + struct iovec *iov; unsigned int i; int error; - u_int iovlen, iovcnt; + u_int iovcnt; iovcnt = uap->iovcnt; - iovlen = iovcnt * sizeof (struct iovec); /* * Check that we have an even number of iovec's * and that we have at least two options. */ - if ((iovcnt & 1) || (iovcnt < 4) || (iovcnt > UIO_MAXIOV)) + if ((iovcnt & 1) || (iovcnt < 4)) return (EINVAL); - - if (iovcnt > UIO_SMALLIOV) { - MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); - needfree = iov; - } else { - iov = aiov; - needfree = NULL; - } - auio.uio_iov = iov; - auio.uio_iovcnt = iovcnt; - auio.uio_segflg = UIO_USERSPACE; - if ((error = copyin(uap->iovp, iov, iovlen))) - goto finish; - + error = copyinuio(uap->iovp, iovcnt, &auio); + if (error) + return (error); + iov = auio->uio_iov; for (i = 0; i < iovcnt; i++) { if (iov->iov_len > MMAXOPTIONLEN) { - error = EINVAL; - goto finish; + free(auio, M_IOV); + return (EINVAL); } iov++; } - error = vfs_nmount(td, uap->flags, &auio); -finish: - if (needfree != NULL) - free(needfree, M_TEMP); + error = vfs_nmount(td, uap->flags, auio); + free(auio, M_IOV); return (error); } diff --git a/sys/sys/uio.h b/sys/sys/uio.h index 600fcff2dc1f..f89c9c4c9d64 100644 --- a/sys/sys/uio.h +++ b/sys/sys/uio.h @@ -77,17 +77,19 @@ struct uio { * IOV_MAX. */ #define UIO_MAXIOV 1024 /* max 1K of iov's */ -#define UIO_SMALLIOV 8 /* 8 on stack, else malloc */ struct vm_object; struct vm_page; +struct uio *cloneuio(struct uio *uiop); int copyinfrom(const void * __restrict src, void * __restrict dst, size_t len, int seg); +int copyiniov(struct iovec *iovp, u_int iovcnt, struct iovec **iov, + int error); int copyinstrfrom(const void * __restrict src, void * __restrict dst, size_t len, size_t * __restrict copied, int seg); +int copyinuio(struct iovec *iovp, u_int iovcnt, struct uio **uiop); void uio_yield(void); -int uiofromiov(struct iovec *iovp, u_int iovcnt, struct uio *auio); int uiomove(void *cp, int n, struct uio *uio); int uiomove_frombuf(void *buf, int buflen, struct uio *uio); int uiomove_fromphys(struct vm_page *ma[], vm_offset_t offset, int n,