Clean up and wash struct iovec and struct uio handling.
Add copyiniov() which copies a struct iovec array in from userland into a malloc'ed struct iovec. Caller frees. Change uiofromiov() to malloc the uio (caller frees) and name it copyinuio() which is more appropriate. Add cloneuio() which returns a malloc'ed copy. Caller frees. Use them throughout.
This commit is contained in:
parent
72118ea9fd
commit
552afd9c12
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=131897
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user