Skip to content

Commit

Permalink
uiomove*_cap: Refactor using UIO_READ/WRITE_CAP permissions
Browse files Browse the repository at this point in the history
This approach is more orthogonal and permits using capability copies
with uiomove_frompyhs or higher level APIs like proc_rwmem without
requiring additional *_cap wrapper routines.
  • Loading branch information
bsdjhb committed May 16, 2024
1 parent bf1b51c commit 98682fe
Show file tree
Hide file tree
Showing 14 changed files with 160 additions and 43 deletions.
5 changes: 5 additions & 0 deletions sys/arm64/arm64/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ memrw(struct cdev *dev, struct uio *uio, int flags)
case UIO_WRITE:
prot = VM_PROT_WRITE;
break;
#if __has_feature(capabilities)
case UIO_READ_CAP:
case UIO_WRITE_CAP:
__assert_unreachable();
#endif
}

if (!kernacc((void *)(uintptr_t)v, cnt, prot)) {
Expand Down
19 changes: 18 additions & 1 deletion sys/arm64/arm64/uio_machdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
int save = 0;
bool mapped;

KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE ||
uio->uio_rw == UIO_READ_CAP || uio->uio_rw == UIO_WRITE_CAP,
("uiomove_fromphys: mode"));
KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
("uiomove_fromphys proc"));
Expand Down Expand Up @@ -97,6 +98,14 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
case UIO_USERSPACE:
maybe_yield();
switch (uio->uio_rw) {
#if __has_feature(capabilities)
case UIO_READ_CAP:
error = copyoutcap(cp, iov->iov_base, cnt);
break;
case UIO_WRITE_CAP:
error = copyincap(iov->iov_base, cp, cnt);
break;
#endif
case UIO_READ:
error = copyout(cp, iov->iov_base, cnt);
break;
Expand All @@ -109,6 +118,14 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
break;
case UIO_SYSSPACE:
switch (uio->uio_rw) {
#if __has_feature(capabilities)
case UIO_READ_CAP:
bcopy_c(PTR2CAP(cp), iov->iov_base, cnt);
break;
case UIO_WRITE_CAP:
bcopy_c(iov->iov_base, PTR2CAP(cp), cnt);
break;
#endif
case UIO_READ:
bcopynocap_c(PTR2CAP(cp), iov->iov_base, cnt);
break;
Expand Down
8 changes: 5 additions & 3 deletions sys/cam/scsi/scsi_target.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,10 +530,11 @@ targwrite(struct cdev *dev, struct uio *uio, int ioflag)
write_len = error = 0;
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
("write - uio_resid %zd\n", uio->uio_resid));
uiomove_enable_cap(uio);
while (uio->uio_resid >= sizeof(user_ccb) && error == 0) {
union ccb *ccb;

error = uiomove_cap((caddr_t)&user_ccb, sizeof(user_ccb), uio);
error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
if (error != 0) {
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH,
("write - uiomove failed (%d)\n", error));
Expand Down Expand Up @@ -811,6 +812,7 @@ targread(struct cdev *dev, struct uio *uio, int ioflag)
user_queue = &softc->user_ccb_queue;
abort_queue = &softc->abort_queue;
CAM_DEBUG(softc->path, CAM_DEBUG_PERIPH, ("targread\n"));
uiomove_enable_cap(uio);

/* If no data is available, wait or return immediately */
cam_periph_lock(softc->periph);
Expand Down Expand Up @@ -850,7 +852,7 @@ targread(struct cdev *dev, struct uio *uio, int ioflag)
if (error != 0)
goto read_fail;
cam_periph_unlock(softc->periph);
error = uiomove_cap((caddr_t)&user_ccb, sizeof(user_ccb), uio);
error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
cam_periph_lock(softc->periph);
if (error != 0)
goto read_fail;
Expand All @@ -873,7 +875,7 @@ targread(struct cdev *dev, struct uio *uio, int ioflag)
goto read_fail;
}
cam_periph_unlock(softc->periph);
error = uiomove_cap((caddr_t)&user_ccb, sizeof(user_ccb), uio);
error = uiomove((caddr_t)&user_ccb, sizeof(user_ccb), uio);
cam_periph_lock(softc->periph);
if (error != 0)
goto read_fail;
Expand Down
5 changes: 5 additions & 0 deletions sys/compat/lindebugfs/lindebugfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@ debugfs_fill(PFS_FILL_ARGS)
&off);
}
break;
#if __has_feature(capabilities)
case UIO_READ_CAP:
case UIO_WRITE_CAP:
__assert_unreachable();
#endif
}

if (d->dm_fops->release)
Expand Down
10 changes: 10 additions & 0 deletions sys/dev/iicbus/iic.c
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,11 @@ iicuio_move(struct iic_cdevpriv *priv, struct uio *uio, int last)
if (error == 0)
error = uiomove(buffer, transferred_bytes, uio);
break;
#if __has_feature(capabilities)
case UIO_READ_CAP:
case UIO_WRITE_CAP:
__assert_unreachable();
#endif
}
}

Expand Down Expand Up @@ -299,6 +304,11 @@ iicuio(struct cdev *dev, struct uio *uio, int ioflag)
case UIO_WRITE:
addr = priv->addr & ~LSB;
break;
#if __has_feature(capabilities)
case UIO_READ_CAP:
case UIO_WRITE_CAP:
__assert_unreachable();
#endif
}

error = iicbus_start(parent, addr, 0);
Expand Down
5 changes: 5 additions & 0 deletions sys/fs/procfs/procfs_osrel.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ procfs_doosrel(PFS_FILL_ARGS)
}
p->p_osrel = osrel;
break;
#if __has_feature(capabilities)
case UIO_READ_CAP:
case UIO_WRITE_CAP:
__assert_unreachable();
#endif
}
return (0);
}
10 changes: 10 additions & 0 deletions sys/kern/kern_physio.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,11 @@ physio(struct cdev *dev, struct uio *uio, int ioflag)
uio->uio_iov[i].iov_len);
racct_add_force(curproc, RACCT_WRITEIOPS, 1);
break;
#if __has_feature(capabilities)
case UIO_READ_CAP:
case UIO_WRITE_CAP:
__assert_unreachable();
#endif
}
PROC_UNLOCK(curproc);
}
Expand All @@ -143,6 +148,11 @@ physio(struct cdev *dev, struct uio *uio, int ioflag)
bp->bio_cmd = BIO_WRITE;
curthread->td_ru.ru_oublock++;
break;
#if __has_feature(capabilities)
case UIO_READ_CAP:
case UIO_WRITE_CAP:
__assert_unreachable();
#endif
}
bp->bio_offset = uio->uio_offset;
base = uio->uio_iov[i].iov_base;
Expand Down
63 changes: 26 additions & 37 deletions sys/kern/subr_uio.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,7 @@ SYSCTL_INT(_kern, KERN_IOV_MAX, iov_max, CTLFLAG_RD, SYSCTL_NULL_INT_PTR, UIO_MA

static uma_zone_t uio_zone;

static int uiomove_flags(void *cp, int n, struct uio *uio, bool nofault,
bool preserve_tags);
static int uiomove_flags(void *cp, int n, struct uio *uio, bool nofault);

static void
uio_init(void *arg __unused)
Expand Down Expand Up @@ -214,35 +213,27 @@ int
uiomove(void *cp, int n, struct uio *uio)
{

return (uiomove_flags(cp, n, uio, false, false));
return (uiomove_flags(cp, n, uio, false));
}

int
uiomove_nofault(void *cp, int n, struct uio *uio)
{

return (uiomove_flags(cp, n, uio, true, false));
return (uiomove_flags(cp, n, uio, true));
}

int
uiomove_cap(void *cp, int n, struct uio *uio)
{

return (uiomove_flags(cp, n, uio, false, true));
}


static int
uiomove_flags(void *cp, int n, struct uio *uio, bool nofault,
bool preserve_tags)
uiomove_flags(void *cp, int n, struct uio *uio, bool nofault)
{
struct iovec *iov;
size_t cnt;
int error, newflags, save;

save = error = 0;

KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE,
KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE ||
uio->uio_rw == UIO_READ_CAP || uio->uio_rw == UIO_WRITE_CAP,
("uiomove: mode"));
KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread,
("uiomove proc"));
Expand Down Expand Up @@ -283,19 +274,19 @@ uiomove_flags(void *cp, int n, struct uio *uio, bool nofault,
case UIO_USERSPACE:
maybe_yield();
switch (uio->uio_rw) {
#if __has_feature(capabilities)
case UIO_READ_CAP:
error = copyoutcap(cp, iov->iov_base, cnt);
break;
case UIO_WRITE_CAP:
error = copyincap(iov->iov_base, cp, cnt);
break;
#endif
case UIO_READ:
if (preserve_tags)
error = copyoutcap(cp, iov->iov_base,
cnt);
else
error = copyout(cp, iov->iov_base, cnt);
error = copyout(cp, iov->iov_base, cnt);
break;
case UIO_WRITE:
if (preserve_tags)
error = copyincap(iov->iov_base, cp,
cnt);
else
error = copyout(cp, iov->iov_base, cnt);
error = copyin(iov->iov_base, cp, cnt);
break;
}
if (error)
Expand All @@ -304,21 +295,19 @@ uiomove_flags(void *cp, int n, struct uio *uio, bool nofault,

case UIO_SYSSPACE:
switch (uio->uio_rw) {
#if __has_feature(capabilities)
case UIO_READ_CAP:
bcopy_c(PTR2CAP(cp), iov->iov_base, cnt);
break;
case UIO_WRITE_CAP:
bcopy_c(iov->iov_base, PTR2CAP(cp), cnt);
break;
#endif
case UIO_READ:
if (preserve_tags)
bcopy_c(PTR2CAP(cp), iov->iov_base,
cnt);
else
bcopynocap_c(PTR2CAP(cp), iov->iov_base,
cnt);
bcopynocap_c(PTR2CAP(cp), iov->iov_base, cnt);
break;
case UIO_WRITE:
if (preserve_tags)
bcopy_c(iov->iov_base, PTR2CAP(cp),
cnt);
else
bcopynocap_c(iov->iov_base, PTR2CAP(cp),
cnt);
bcopynocap_c(iov->iov_base, PTR2CAP(cp), cnt);
break;
}
break;
Expand Down
23 changes: 23 additions & 0 deletions sys/kern/vfs_vnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -1268,6 +1268,11 @@ vn_io_fault_doio(struct vn_io_fault_args *args, struct uio *uio,
error = VOP_WRITE(args->args.vop_args.vp, uio,
args->flags, args->cred);
break;
#if __has_feature(capabilities)
case UIO_READ_CAP:
case UIO_WRITE_CAP:
__assert_unreachable();
#endif
}
break;
default:
Expand Down Expand Up @@ -1559,6 +1564,14 @@ vn_io_fault_uiomove(char *data, int xfersize, struct uio *uio)
case UIO_READ:
transp_uio.uio_rw = UIO_WRITE;
break;
#if __has_feature(capabilities)
case UIO_WRITE_CAP:
transp_uio.uio_rw = UIO_READ_CAP;
break;
case UIO_READ_CAP:
transp_uio.uio_rw = UIO_WRITE_CAP;
break;
#endif
}
transp_uio.uio_td = uio->uio_td;
error = uiomove_fromphys(td->td_ma,
Expand Down Expand Up @@ -1603,6 +1616,16 @@ vn_io_fault_pgmove(vm_page_t ma[], vm_offset_t offset, int xfersize,
pmap_copy_pages(ma, offset, td->td_ma, iov_base & PAGE_MASK,
cnt);
break;
#if __has_feature(capabilities)
case UIO_WRITE_CAP:
pmap_copy_pages_tags(td->td_ma, iov_base & PAGE_MASK, ma,
offset, cnt);
break;
case UIO_READ_CAP:
pmap_copy_pages_tags(ma, offset, td->td_ma,
iov_base & PAGE_MASK, cnt);
break;
#endif
}
pgadv = ((iov_base + cnt) >> PAGE_SHIFT) - (iov_base >> PAGE_SHIFT);
td->td_ma += pgadv;
Expand Down
5 changes: 5 additions & 0 deletions sys/riscv/riscv/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ memrw(struct cdev *dev, struct uio *uio, int flags)
case UIO_WRITE:
prot = VM_PROT_WRITE;
break;
#if __has_feature(capabilities)
case UIO_READ_CAP:
case UIO_WRITE_CAP:
__assert_unreachable();
#endif
}

if (!kernacc((void *)(uintptr_t)v, cnt, prot)) {
Expand Down
16 changes: 16 additions & 0 deletions sys/riscv/riscv/uio_machdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
case UIO_USERSPACE:
maybe_yield();
switch (uio->uio_rw) {
#if __has_feature(capabilities)
case UIO_READ_CAP:
error = copyoutcap(cp, iov->iov_base, cnt);
break;
case UIO_WRITE_CAP:
error = copyincap(iov->iov_base, cp, cnt);
break;
#endif
case UIO_READ:
error = copyout(cp, iov->iov_base, cnt);
break;
Expand All @@ -109,6 +117,14 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
break;
case UIO_SYSSPACE:
switch (uio->uio_rw) {
#if __has_feature(capabilities)
case UIO_READ_CAP:
bcopy_c(PTR2CAP(cp), iov->iov_base, cnt);
break;
case UIO_WRITE_CAP:
bcopy_c(iov->iov_base, PTR2CAP(cp), cnt);
break;
#endif
case UIO_READ:
bcopynocap_c(PTR2CAP(cp), iov->iov_base, cnt);
break;
Expand Down
9 changes: 8 additions & 1 deletion sys/sys/_uio.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,14 @@
#if __BSD_VISIBLE
enum uio_rw {
UIO_READ,
UIO_WRITE
UIO_WRITE,
#if __has_feature(capabilities)
UIO_READ_CAP,
UIO_WRITE_CAP
#else
UIO_READ_CAP = UIO_READ,
UIO_WRITE_CAP = UIO_WRITE
#endif
};

/* Segment flag values. */
Expand Down

0 comments on commit 98682fe

Please sign in to comment.