Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions sbin/ipf/ipftest/ip_fil.c
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ ipf_checkv6sum(fin)
* See above for description, except that all addressing is in user space.
*/
int
copyoutptr(softc, src, dst, size)
copyout_indirect(softc, src, dst, size)
void *src, *dst;
size_t size;
{
Expand All @@ -635,7 +635,7 @@ copyoutptr(softc, src, dst, size)
* See above for description, except that all addressing is in user space.
*/
int
copyinptr(src, dst, size)
copyin_indirect(src, dst, size)
void *src, *dst;
size_t size;
{
Expand Down
4 changes: 2 additions & 2 deletions sbin/ipf/libipf/interror.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ static ipf_error_entry_t *find_error(int);
static ipf_error_entry_t ipf_errors[IPF_NUM_ERRORS] = {
{ 1, "auth table locked/full" },
{ 2, "" },
{ 3, "copyinptr received bad address" },
{ 4, "copyoutptr received bad address" },
{ 3, "copyin_indirect received bad address" },
{ 4, "copyout_indirect received bad address" },
{ 5, "" },
{ 6, "cannot load a rule with FR_T_BUILTIN flag set" },
{ 7, "internal rule without FR_T_BUILDINT flag set" },
Expand Down
6 changes: 6 additions & 0 deletions share/man/man9/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -918,9 +918,13 @@ MLINKS+=casuword.9 casueword.9 \
casuword.9 casuword32.9
MLINKS+=copy.9 copyin.9 \
copy.9 copyin_nofault.9 \
copy.9 copyinptr.9 \
copy.9 copyinptr_nofault.9 \
copy.9 copyinstr.9 \
copy.9 copyout.9 \
copy.9 copyout_nofault.9 \
copy.9 copyoutptr.9 \
copy.9 copyoutptr_nofault.9 \
copy.9 copystr.9
MLINKS+=counter.9 counter_u64_alloc.9 \
counter.9 counter_u64_free.9 \
Expand Down Expand Up @@ -2149,7 +2153,9 @@ MLINKS+=socket.9 soabort.9 \
socket.9 solisten_proto_check.9 \
socket.9 sonewconn.9 \
socket.9 sooptcopyin.9 \
socket.9 sooptcopyinptr.9 \
socket.9 sooptcopyout.9 \
socket.9 sooptcopyoutptr.9 \
socket.9 sopoll.9 \
socket.9 sopoll_generic.9 \
socket.9 soreceive.9 \
Expand Down
43 changes: 40 additions & 3 deletions share/man/man9/copy.9
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,19 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd May 11, 2020
.Dd December 9, 2025
.Dt COPY 9
.Os
.Sh NAME
.Nm copy ,
.Nm copyin ,
.Nm copyin_nofault ,
.Nm copyinptr ,
.Nm copyinptr_nofault ,
.Nm copyout ,
.Nm copyout_nofault ,
.Nm copyoutptr ,
.Nm copyoutptr_nofault ,
.Nm copystr ,
.Nm copyinstr
.Nd heterogenous address space copy functions
Expand All @@ -52,9 +56,17 @@
.Ft int
.Fn copyin_nofault "const void *uaddr" "void *kaddr" "size_t len"
.Ft int
.Fn copyinptr "const void *uaddr" "void *kaddr" "size_t len"
.Ft int
.Fn copyinptr_nofault "const void *uaddr" "void *kaddr" "size_t len"
.Ft int
.Fn copyout "const void *kaddr" "void *uaddr" "size_t len"
.Ft int
.Fn copyout_nofault "const void *kaddr" "void *uaddr" "size_t len"
.Ft int
.Fn copyoutptr "const void *kaddr" "void *uaddr" "size_t len"
.Ft int
.Fn copyoutptr_nofault "const void *kaddr" "void *uaddr" "size_t len"
.Ft int __deprecated
.Fn copystr "const void *kfaddr" "void *kdaddr" "size_t len" "size_t *done"
.Ft int
Expand All @@ -80,7 +92,14 @@ functions copy
bytes of data from the user-space address
.Fa uaddr
to the kernel-space address
.Fa kaddr .
.Fa kaddr
without preserving pointer provenance.
The
.Fn copyinptr
and
.Fn copyinptr_nofault
functions do the same,
but preserve the provenance of copied pointers.
.Pp
The
.Fn copyout
Expand All @@ -91,7 +110,14 @@ functions copy
bytes of data from the kernel-space address
.Fa kaddr
to the user-space address
.Fa uaddr .
.Fa uaddr
without perservice pointer provenance.
The
.Fn copyoutptr
and
.Fn copyoutptr_nofault
functions do the same,
but preserve the provenance of copied pointers.
.Pp
The
.Fn copyin_nofault
Expand All @@ -104,6 +130,17 @@ read and write access, respectively, and neither the source nor
destination addresses may be pageable.
.Pp
The
.Fn copyinptr ,
.Fn copyinptr_nofault ,
.Fn copyoutptr ,
and
.Fn copyoutptr_nofault
functions must be used when copying data which may contain pointers and
they may be used anywhere,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be tempted to drop "and they may be used anywhere", and just say "must be used when copying data which contains pointers, but they should only be used when necessary..."

but they should be used only when necessicary to limit the numeber of
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
but they should be used only when necessicary to limit the numeber of
but they should be used only when necessary to limit the number of

code paths that could leak pointers.
.Pp
The
.Fn copystr
function copies a NUL-terminated string, at most
.Fa len
Expand Down
11 changes: 10 additions & 1 deletion share/man/man9/socket.9
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.Dd September 6, 2022
.Dd December 9, 2025
.Dt SOCKET 9
.Os
.Sh NAME
Expand Down Expand Up @@ -146,7 +146,10 @@
.Ft int
.Fn sooptcopyin "struct sockopt *sopt" "void *buf" "size_t len" "size_t minlen"
.Ft int
.Fn sooptcopyinptr "struct sockopt *sopt" "void *buf" "size_t len" "size_t minlen"
.Ft int
.Fn sooptcopyout "struct sockopt *sopt" "const void *buf" "size_t len"
.Fn sooptcopyoutptr "struct sockopt *sopt" "const void *buf" "size_t len"
.Sh DESCRIPTION
The kernel
.Nm
Expand Down Expand Up @@ -577,6 +580,12 @@ and
are useful for transferring
.Vt struct sockopt
data between user and kernel code.
They do not preserve pointer provenance.
If the copied data contains pointers, the
.Fn sooptcopyinptr
and
.Fn sooptcopyoutptr
functions must be used instead.
.Sh SEE ALSO
.Xr bind 2 ,
.Xr close 2 ,
Expand Down
2 changes: 1 addition & 1 deletion sys/amd64/linux32/linux32_machdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ linux_copyout_rusage(struct rusage *ru, void *uaddr)
int
linux_readv(struct thread *td, struct linux_readv_args *uap)
{
return (user_readv(td, uap->fd, __USER_CAP_ARRAY(uap->iovp,
return (user_readv(td, uap->fd, USER_PTR_ARRAY(uap->iovp,
uap->iovcnt), uap->iovcnt, freebsd32_copyinuio));
}

Expand Down
12 changes: 6 additions & 6 deletions sys/arm64/arm64/copyinout.S
Original file line number Diff line number Diff line change
Expand Up @@ -269,9 +269,9 @@ ending:
* Copy specified amount of data from the user to kernel space, preserving
* capability tags
*
* int copyincap(const void * __capability uaddr, void *kdaddr, size_t len)
* int copyinptr(const void * __capability uaddr, void *kdaddr, size_t len)
*/
ENTRY(copyincap)
ENTRY(copyinptr)
cbz x2, 1f
check_user_access 0, 2, copyio_fault_nopcb

Expand All @@ -295,15 +295,15 @@ ENTRY(copyincap)

1: mov x0, xzr /* return 0 */
RETURN
END(copyincap)
END(copyinptr)

/*
* Copy specified amount of data from kernel to the user space, preserving
* capability tags
*
* int copyoutcap(const void *kaddr, void * __capability udaddr, size_t len)
* int copyoutptr(const void *kaddr, void * __capability udaddr, size_t len)
*/
ENTRY(copyoutcap)
ENTRY(copyoutptr)
cbz x2, 1f
check_user_access 1, 2, copyio_fault_nopcb

Expand All @@ -327,7 +327,7 @@ ENTRY(copyoutcap)

1: mov x0, xzr /* return 0 */
RETURN
END(copyoutcap)
END(copyoutptr)

/*
* Local helpers to copy through capabilities
Expand Down
4 changes: 2 additions & 2 deletions sys/arm64/arm64/exec_machdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -992,7 +992,7 @@ sys_sigreturn(struct thread *td, struct sigreturn_args *uap)
ucontext_t uc;
int error;

if (copyincap(uap->sigcntxp, &uc, sizeof(uc)))
if (copyinptr(uap->sigcntxp, &uc, sizeof(uc)))
return (EFAULT);

/* Stop an interrupt from causing the sve state to be dropped */
Expand Down Expand Up @@ -1146,7 +1146,7 @@ sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
fp = (struct sigframe * __capability)STACKALIGN(fp);

/* Copy the sigframe out to the user's stack. */
if (copyoutcap(&frame, fp, sizeof(*fp)) != 0) {
if (copyoutptr(&frame, fp, sizeof(*fp)) != 0) {
/* Process has trashed its stack. Kill it. */
CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%p", td,
(__cheri_fromcap void *)fp);
Expand Down
8 changes: 4 additions & 4 deletions sys/arm64/arm64/freebsd64_machdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ freebsd64_set_mcontext(struct thread *td, mcontext64_t *mcp)

memset(&mc, 0, sizeof(mc));
if (mcp->mc_flags & _MC_CAP_VALID) {
error = copyincap(__USER_CAP(mcp->mc_capregs,
error = copyinptr(USER_PTR(mcp->mc_capregs,
sizeof(mc.mc_capregs)), &mc.mc_capregs,
sizeof(mc.mc_capregs));
if (error)
Expand Down Expand Up @@ -308,7 +308,7 @@ freebsd64_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
PROC_UNLOCK(td->td_proc);

/* Copy the capability registers out to the user's stack. */
if (copyoutcap(&mc.mc_capregs, __USER_CAP(capregs,
if (copyoutptr(&mc.mc_capregs, USER_PTR(capregs,
sizeof(mc.mc_capregs)), sizeof(mc.mc_capregs)) != 0) {
PROC_LOCK(p);
printf("pid %d, tid %d: could not copy out cap registers\n",
Expand All @@ -318,7 +318,7 @@ freebsd64_sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
}

/* Copy the sigframe out to the user's stack. */
if (copyoutcap(&frame, __USER_CAP(fp, sizeof(struct sigframe64)),
if (copyoutptr(&frame, USER_PTR(fp, sizeof(struct sigframe64)),
sizeof(struct sigframe64)) != 0) {
/* Process has trashed its stack. Kill it. */
CTR2(KTR_SIG, "sendsig: sigexit td=%p fp=%lx", td, fp);
Expand Down Expand Up @@ -347,7 +347,7 @@ freebsd64_sigreturn(struct thread *td, struct freebsd64_sigreturn_args *uap)
ucontext64_t uc;
int error;

error = copyincap(__USER_CAP_OBJ(uap->sigcntxp), &uc, sizeof(uc));
error = copyinptr(USER_PTR_OBJ(uap->sigcntxp), &uc, sizeof(uc));
if (error != 0)
return (error);

Expand Down
2 changes: 1 addition & 1 deletion sys/arm64/arm64/trap.c
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ cpu_fetch_syscall_args(struct thread *td)

#if __has_feature(capabilities)
if (__predict_false(stack_args != NULL)) {
error = copyincap(stack_args, dst_ap, sa->callp->sy_narg *
error = copyinptr(stack_args, dst_ap, sa->callp->sy_narg *
sizeof(*dst_ap));
if (error)
return (error);
Expand Down
4 changes: 2 additions & 2 deletions sys/arm64/arm64/uio_machdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
switch (uio->uio_rw) {
#if __has_feature(capabilities)
case UIO_READ_CAP:
error = copyoutcap(cp, iov->iov_base, cnt);
error = copyoutptr(cp, iov->iov_base, cnt);
break;
case UIO_WRITE_CAP:
error = copyincap(iov->iov_base, cp, cnt);
error = copyinptr(iov->iov_base, cp, cnt);
break;
#endif
case UIO_READ:
Expand Down
2 changes: 1 addition & 1 deletion sys/arm64/conf/GENERIC-MORELLO
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ options CHERI_CAPREVOKE_STATS
options CHERI_CAPREVOKE_FAST_COPYIN
options CHERI_CAPREVOKE_CLEARTAGS

# Needs porting to use __USER_CAP
# Needs porting to use USER_PTR
nooptions COMPAT_FREEBSD32

# Doesn't build with Morello LLVM
Expand Down
2 changes: 1 addition & 1 deletion sys/cam/ctl/ctl_frontend_iscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -1927,7 +1927,7 @@ cfiscsi_ioctl_listen(struct ctl_iscsi *ci)
return;
}

error = getsockaddr(&sa, __USER_CAP(cilp->addr, cilp->addrlen),
error = getsockaddr(&sa, USER_PTR(cilp->addr, cilp->addrlen),
cilp->addrlen);
if (error != 0) {
CFISCSI_DEBUG("getsockaddr, error %d", error);
Expand Down
4 changes: 2 additions & 2 deletions sys/cam/scsi/scsi_cd.c
Original file line number Diff line number Diff line change
Expand Up @@ -1750,12 +1750,12 @@ te_data_get_ptr(void *irtep, u_long cmd)
return (irteup->irte.data);
#ifdef COMPAT_FREEBSD32
case sizeof(irteup->irte32):
return (__USER_CAP(irteup->irte32.data,
return (USER_PTR(irteup->irte32.data,
irteup->irte32.data_len));
#endif
#ifdef COMPAT_FREEBSD64
case sizeof(irteup->irte64):
return (__USER_CAP(irteup->irte64.data,
return (USER_PTR(irteup->irte64.data,
irteup->irte64.data_len));
#endif
default:
Expand Down
10 changes: 5 additions & 5 deletions sys/cam/scsi/scsi_enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ enc_ioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag,
error = EINVAL;
break;
}
error = copyincap(addr, &sstr, sizeof(sstr));
error = copyinptr(addr, &sstr, sizeof(sstr));
if (error)
break;
cam_periph_lock(periph);
Expand Down Expand Up @@ -504,7 +504,7 @@ enc_ioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag,
case ENCIOC_GETELMDESC: {
encioc_elm_desc_t elmd;

error = copyincap(addr, &elmd, sizeof(elmd));
error = copyinptr(addr, &elmd, sizeof(elmd));
if (error)
break;
if (elmd.elm_idx >= cache->nelms) {
Expand All @@ -517,7 +517,7 @@ enc_ioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag,
break;
} else
elmd.elm_desc_len = 0;
error = copyoutcap(&elmd, addr, sizeof(elmd));
error = copyoutptr(&elmd, addr, sizeof(elmd));
break;
}
case ENCIOC_GETELMDEVNAMES: {
Expand All @@ -527,7 +527,7 @@ enc_ioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag,
error = EINVAL;
break;
}
error = copyincap(addr, &elmdn, sizeof(elmdn));
error = copyinptr(addr, &elmdn, sizeof(elmdn));
if (error)
break;
if (elmdn.elm_idx >= cache->nelms) {
Expand All @@ -539,7 +539,7 @@ enc_ioctl(struct cdev *dev, u_long cmd, caddr_t arg_addr, int flag,
cam_periph_unlock(periph);
if (error)
break;
error = copyoutcap(&elmdn, addr, sizeof(elmdn));
error = copyoutptr(&elmdn, addr, sizeof(elmdn));
break;
}
case ENCIOC_SETELMSTAT: {
Expand Down
4 changes: 2 additions & 2 deletions sys/cam/scsi/scsi_pass.c
Original file line number Diff line number Diff line change
Expand Up @@ -1878,7 +1878,7 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread
xpt_print(periph->path, "Copying user CCB %p to "
"kernel address %p\n", *user_ccb, ccb);
#endif
error = copyincap(*user_ccb, ccb, sizeof(*ccb));
error = copyinptr(*user_ccb, ccb, sizeof(*ccb));
if (error != 0) {
xpt_print(periph->path, "Copy of user CCB %p to "
"kernel address %p failed with error %d\n",
Expand Down Expand Up @@ -2069,7 +2069,7 @@ passdoioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread
"kernel address %p\n", *user_ccb, &io_req->ccb);
#endif

error = copyoutcap(&io_req->ccb, *user_ccb, sizeof(union ccb));
error = copyoutptr(&io_req->ccb, *user_ccb, sizeof(union ccb));
if (error != 0) {
xpt_print(periph->path, "Copy to user CCB %p from "
"kernel address %p failed with error %d\n",
Expand Down
Loading
Loading