Skip to content

Commit

Permalink
Abstract UIO allocation and deallocation.
Browse files Browse the repository at this point in the history
Introduce the allocuio() and freeuio() functions to allocate and
deallocate struct uio. This hides the actual allocator interface, so it
is easier to modify the sub-allocation layout of struct uio and the
corresponding iovec array.

Obtained from:	CheriBSD
Reviewed by:	kib, markj
MFC after:	2 weeks
Sponsored by:	CHaOS, EPSRC grant EP/V000292/1
Differential Revision:	https://reviews.freebsd.org/D43711
  • Loading branch information
qwattash authored and markjdb committed Feb 10, 2024
1 parent f82e982 commit 61cc483
Show file tree
Hide file tree
Showing 14 changed files with 66 additions and 45 deletions.
2 changes: 1 addition & 1 deletion sys/amd64/linux32/linux32_machdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ linux_readv(struct thread *td, struct linux_readv_args *uap)
if (error)
return (error);
error = kern_readv(td, uap->fd, auio);
free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand Down
2 changes: 1 addition & 1 deletion sys/cddl/compat/opensolaris/kern/opensolaris_uio.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ uiocopy(void *p, size_t n, enum uio_rw rw, struct uio *uio, size_t *cbytes)
error = vn_io_fault_uiomove(p, n, uio_clone);
*cbytes = uio->uio_resid - uio_clone->uio_resid;
if (uio_clone != &small_uio_clone)
free(uio_clone, M_IOV);
freeuio(uio_clone);
return (error);
}

Expand Down
29 changes: 13 additions & 16 deletions sys/compat/freebsd32/freebsd32_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1196,32 +1196,29 @@ freebsd32_copyinuio(struct iovec32 *iovp, u_int iovcnt, struct uio **uiop)
struct iovec32 iov32;
struct iovec *iov;
struct uio *uio;
u_int iovlen;
int error, i;

*uiop = NULL;
if (iovcnt > UIO_MAXIOV)
return (EINVAL);
iovlen = iovcnt * sizeof(struct iovec);
uio = malloc(iovlen + sizeof *uio, M_IOV, M_WAITOK);
iov = (struct iovec *)(uio + 1);
uio = allocuio(iovcnt);
iov = uio->uio_iov;
for (i = 0; i < iovcnt; i++) {
error = copyin(&iovp[i], &iov32, sizeof(struct iovec32));
if (error) {
free(uio, M_IOV);
freeuio(uio);
return (error);
}
iov[i].iov_base = PTRIN(iov32.iov_base);
iov[i].iov_len = iov32.iov_len;
}
uio->uio_iov = iov;
uio->uio_iovcnt = iovcnt;
uio->uio_segflg = UIO_USERSPACE;
uio->uio_offset = -1;
uio->uio_resid = 0;
for (i = 0; i < iovcnt; i++) {
if (iov->iov_len > INT_MAX - uio->uio_resid) {
free(uio, M_IOV);
freeuio(uio);
return (EINVAL);
}
uio->uio_resid += iov->iov_len;
Expand All @@ -1241,7 +1238,7 @@ freebsd32_readv(struct thread *td, struct freebsd32_readv_args *uap)
if (error)
return (error);
error = kern_readv(td, uap->fd, auio);
free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand All @@ -1255,7 +1252,7 @@ freebsd32_writev(struct thread *td, struct freebsd32_writev_args *uap)
if (error)
return (error);
error = kern_writev(td, uap->fd, auio);
free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand All @@ -1269,7 +1266,7 @@ freebsd32_preadv(struct thread *td, struct freebsd32_preadv_args *uap)
if (error)
return (error);
error = kern_preadv(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand All @@ -1283,7 +1280,7 @@ freebsd32_pwritev(struct thread *td, struct freebsd32_pwritev_args *uap)
if (error)
return (error);
error = kern_pwritev(td, uap->fd, auio, PAIR32TO64(off_t,uap->offset));
free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand Down Expand Up @@ -2199,9 +2196,9 @@ freebsd32_do_sendfile(struct thread *td,

out:
if (hdr_uio)
free(hdr_uio, M_IOV);
freeuio(hdr_uio);
if (trl_uio)
free(trl_uio, M_IOV);
freeuio(trl_uio);
return (error);
}

Expand Down Expand Up @@ -2780,7 +2777,7 @@ freebsd32_jail_set(struct thread *td, struct freebsd32_jail_set_args *uap)
if (error)
return (error);
error = kern_jail_set(td, auio, uap->flags);
free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand All @@ -2807,7 +2804,7 @@ freebsd32_jail_get(struct thread *td, struct freebsd32_jail_get_args *uap)
if (error != 0)
break;
}
free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand Down Expand Up @@ -3540,7 +3537,7 @@ freebsd32_nmount(struct thread *td,
return (error);
error = vfs_donmount(td, flags, auio);

free(auio, M_IOV);
freeuio(auio);
return error;
}

Expand Down
6 changes: 3 additions & 3 deletions sys/compat/linux/linux_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1038,7 +1038,7 @@ linux_preadv(struct thread *td, struct linux_preadv_args *uap)
if (error != 0)
return (error);
error = kern_preadv(td, uap->fd, auio, offset);
free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand All @@ -1065,7 +1065,7 @@ linux_pwritev(struct thread *td, struct linux_pwritev_args *uap)
if (error != 0)
return (error);
error = kern_pwritev(td, uap->fd, auio, offset);
free(auio, M_IOV);
freeuio(auio);
return (linux_enobufs2eagain(td, uap->fd, error));
}

Expand Down Expand Up @@ -1872,6 +1872,6 @@ linux_writev(struct thread *td, struct linux_writev_args *args)
if (error != 0)
return (error);
error = kern_writev(td, args->fd, auio);
free(auio, M_IOV);
freeuio(auio);
return (linux_enobufs2eagain(td, args->fd, error));
}
6 changes: 3 additions & 3 deletions sys/kern/kern_jail.c
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ sys_jail_set(struct thread *td, struct jail_set_args *uap)
if (error)
return (error);
error = kern_jail_set(td, auio, uap->flags);
free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand Down Expand Up @@ -2296,8 +2296,8 @@ sys_jail_get(struct thread *td, struct jail_get_args *uap)
error = kern_jail_get(td, auio, uap->flags);
if (error == 0)
error = copyout(auio->uio_iov, uap->iovp,
uap->iovcnt * sizeof (struct iovec));
free(auio, M_IOV);
uap->iovcnt * sizeof(struct iovec));
freeuio(auio);
return (error);
}

Expand Down
4 changes: 2 additions & 2 deletions sys/kern/kern_ktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -768,15 +768,15 @@ ktrgenio(int fd, enum uio_rw rw, struct uio *uio, int error)
char *buf;

if (error) {
free(uio, M_IOV);
freeuio(uio);
return;
}
uio->uio_offset = 0;
uio->uio_rw = UIO_WRITE;
datalen = MIN(uio->uio_resid, ktr_geniosize);
buf = malloc(datalen, M_KTRACE, M_WAITOK);
error = uiomove(buf, datalen, uio);
free(uio, M_IOV);
freeuio(uio);
if (error) {
free(buf, M_KTRACE);
return;
Expand Down
4 changes: 2 additions & 2 deletions sys/kern/kern_sendfile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1331,8 +1331,8 @@ sendfile(struct thread *td, struct sendfile_args *uap, int compat)
(void)copyout(&sbytes, uap->sbytes, sizeof(off_t));

out:
free(hdr_uio, M_IOV);
free(trl_uio, M_IOV);
freeuio(hdr_uio);
freeuio(trl_uio);
return (error);
}

Expand Down
2 changes: 1 addition & 1 deletion sys/kern/subr_prf.c
Original file line number Diff line number Diff line change
Expand Up @@ -386,7 +386,7 @@ log_console(struct uio *uio)
msglogstr(consbuffer, pri, /*filter_cr*/ 1);
}
msgbuftrigger = 1;
free(uio, M_IOV);
freeuio(uio);
free(consbuffer, M_TEMP);
}

Expand Down
38 changes: 30 additions & 8 deletions sys/kern/subr_uio.c
Original file line number Diff line number Diff line change
Expand Up @@ -373,21 +373,20 @@ copyinuio(const struct iovec *iovp, u_int iovcnt, struct uio **uiop)
if (iovcnt > UIO_MAXIOV)
return (EINVAL);
iovlen = iovcnt * sizeof(struct iovec);
uio = malloc(iovlen + sizeof(*uio), M_IOV, M_WAITOK);
iov = (struct iovec *)(uio + 1);
uio = allocuio(iovcnt);
iov = uio->uio_iov;
error = copyin(iovp, iov, iovlen);
if (error) {
free(uio, M_IOV);
if (error != 0) {
freeuio(uio);
return (error);
}
uio->uio_iov = iov;
uio->uio_iovcnt = iovcnt;
uio->uio_segflg = UIO_USERSPACE;
uio->uio_offset = -1;
uio->uio_resid = 0;
for (i = 0; i < iovcnt; i++) {
if (iov->iov_len > IOSIZE_MAX - uio->uio_resid) {
free(uio, M_IOV);
freeuio(uio);
return (EINVAL);
}
uio->uio_resid += iov->iov_len;
Expand All @@ -397,16 +396,39 @@ copyinuio(const struct iovec *iovp, u_int iovcnt, struct uio **uiop)
return (0);
}

struct uio *
allocuio(u_int iovcnt)
{
struct uio *uio;
int iovlen;

KASSERT(iovcnt <= UIO_MAXIOV,
("Requested %u iovecs exceed UIO_MAXIOV", iovcnt));
iovlen = iovcnt * sizeof(struct iovec);
uio = malloc(iovlen + sizeof(*uio), M_IOV, M_WAITOK);
uio->uio_iov = (struct iovec *)(uio + 1);

return (uio);
}

void
freeuio(struct uio *uio)
{
free(uio, M_IOV);
}

struct uio *
cloneuio(struct uio *uiop)
{
struct iovec *iov;
struct uio *uio;
int iovlen;

iovlen = uiop->uio_iovcnt * sizeof(struct iovec);
uio = malloc(iovlen + sizeof(*uio), M_IOV, M_WAITOK);
uio = allocuio(uiop->uio_iovcnt);
iov = uio->uio_iov;
*uio = *uiop;
uio->uio_iov = (struct iovec *)(uio + 1);
uio->uio_iov = iov;
bcopy(uiop->uio_iov, uio->uio_iov, iovlen);
return (uio);
}
Expand Down
8 changes: 4 additions & 4 deletions sys/kern/sys_generic.c
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ sys_readv(struct thread *td, struct readv_args *uap)
if (error)
return (error);
error = kern_readv(td, uap->fd, auio);
free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand Down Expand Up @@ -310,7 +310,7 @@ sys_preadv(struct thread *td, struct preadv_args *uap)
if (error)
return (error);
error = kern_preadv(td, uap->fd, auio, uap->offset);
free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand Down Expand Up @@ -473,7 +473,7 @@ sys_writev(struct thread *td, struct writev_args *uap)
if (error)
return (error);
error = kern_writev(td, uap->fd, auio);
free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand Down Expand Up @@ -512,7 +512,7 @@ sys_pwritev(struct thread *td, struct pwritev_args *uap)
if (error)
return (error);
error = kern_pwritev(td, uap->fd, auio, uap->offset);
free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand Down
4 changes: 2 additions & 2 deletions sys/kern/vfs_aio.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,7 +555,7 @@ aio_free_entry(struct kaiocb *job)
fdrop(job->fd_file, curthread);
crfree(job->cred);
if (job->uiop != &job->uio)
free(job->uiop, M_IOV);
freeuio(job->uiop);
uma_zfree(aiocb_zone, job);
AIO_LOCK(ki);

Expand Down Expand Up @@ -1728,7 +1728,7 @@ aio_aqueue(struct thread *td, struct aiocb *ujob, struct aioliojob *lj,
knlist_delete(&job->klist, curthread, 0);
err2:
if (job->uiop != &job->uio)
free(job->uiop, M_IOV);
freeuio(job->uiop);
uma_zfree(aiocb_zone, job);
err1:
ops->store_error(ujob, error);
Expand Down
2 changes: 1 addition & 1 deletion sys/kern/vfs_mount.c
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ sys_nmount(struct thread *td, struct nmount_args *uap)
}
error = vfs_donmount(td, flags, auio);

free(auio, M_IOV);
freeuio(auio);
return (error);
}

Expand Down
2 changes: 1 addition & 1 deletion sys/kern/vfs_vnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1442,7 +1442,7 @@ vn_io_fault1(struct vnode *vp, struct uio *uio, struct vn_io_fault_args *args,
td->td_ma_cnt = prev_td_ma_cnt;
curthread_pflags_restore(saveheld);
out:
free(uio_clone, M_IOV);
freeuio(uio_clone);
return (error);
}

Expand Down
2 changes: 2 additions & 0 deletions sys/sys/uio.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ struct vm_object;
struct vm_page;
struct bus_dma_segment;

struct uio *allocuio(u_int iovcnt);
void freeuio(struct uio *uio);
struct uio *cloneuio(struct uio *uiop);
int copyiniov(const struct iovec *iovp, u_int iovcnt, struct iovec **iov,
int error);
Expand Down

0 comments on commit 61cc483

Please sign in to comment.