git: b517edb8deed - main - CHERI: declare copy{in,out}ptr{,_nofault}

From: Brooks Davis <brooks_at_FreeBSD.org>
Date: Mon, 29 Jun 2026 13:01:39 UTC
The branch main has been updated by brooks:

URL: https://cgit.FreeBSD.org/src/commit/?id=b517edb8deed23b8c616f0ad4453e4dee7b0ac0f

commit b517edb8deed23b8c616f0ad4453e4dee7b0ac0f
Author:     Brooks Davis <brooks@FreeBSD.org>
AuthorDate: 2026-06-29 12:58:52 +0000
Commit:     Brooks Davis <brooks@FreeBSD.org>
CommitDate: 2026-06-29 12:59:29 +0000

    CHERI: declare copy{in,out}ptr{,_nofault}
    
    These provenance-preserving functions are to be used when copying
    objects that are expected to contain pointers.  Data buffers which do
    not contain pointers should be copied by the traditional copyin/copyout
    functions which *do not* preserve pointer provenance (on CHERI they
    clear validity tags).
    
    NOTE: Going forward, this requires changes when adding new syscalls or
    ioctl that take pointers to objects containing pointers.  Fortunately,
    the vast majority (>90%) of copyin and copyout statements do not copy
    pointers and require no change.  Failure to make the chance will have no
    effect on non-CHERI architectures.
    
    Reviewed by:    kib, markj
    Effort:         CHERI upstreaming
    Sponsored by:   DARPA, AFRL, Innovate UK
    Differential Revision:  https://reviews.freebsd.org/D57663
---
 share/man/man9/copy.9 | 49 ++++++++++++++++++++++++++++++++++++++++++++-----
 sys/kern/subr_uio.c   | 24 ++++++++++++++++++++++++
 sys/sys/systm.h       | 18 ++++++++++++++++++
 3 files changed, 86 insertions(+), 5 deletions(-)

diff --git a/share/man/man9/copy.9 b/share/man/man9/copy.9
index fe51bbd12704..a1aa75e2c84f 100644
--- a/share/man/man9/copy.9
+++ b/share/man/man9/copy.9
@@ -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 June 29, 2026
 .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 heterogeneous address space copy functions
@@ -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
@@ -81,7 +93,15 @@ functions copy
 bytes of data from the user-space address
 .Fa uaddr
 to the kernel-space address
-.Fa kaddr .
+.Fa kaddr
+without preserving the provenance of pointers in the copied object
+.Pq see Xr memory_model 7 for further information .
+The
+.Fn copyinptr
+and
+.Fn copyinptr_nofault
+functions do the same,
+but preserves the provenance of copied pointers to user-space.
 .Pp
 The
 .Fn copyout
@@ -92,12 +112,21 @@ functions copy
 bytes of data from the kernel-space address
 .Fa kaddr
 to the user-space address
-.Fa uaddr .
+.Fa uaddr
+without preserving the provenance of pointers in the copied object.
+The
+.Fn copyoutptr
+and
+.Fn copyoutptr_nofault
+functions do the same,
+but preserves the provenance of copied pointers to user-space.
 .Pp
 The
-.Fn copyin_nofault
+.Fn copyin_nofault ,
+.Fn copyinptr_nofault ,
+.Fn copyout_nofault ,
 and
-.Fn copyout_nofault
+.Fn copyoutptr_nofault
 functions require that the kernel-space and user-space data be
 accessible without incurring a page fault.
 The source and destination addresses must be physically mapped for
@@ -105,6 +134,16 @@ 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,
+but they should only be used when necessary to limit the number of
+code paths that could leak pointers between address spaces.
+.Pp
+The
 .Fn copystr
 function copies a NUL-terminated string, at most
 .Fa len
diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c
index e2059d3813d4..ea75c6abc539 100644
--- a/sys/kern/subr_uio.c
+++ b/sys/kern/subr_uio.c
@@ -88,6 +88,30 @@ copyout_nofault(const void *kaddr, void *udaddr, size_t len)
 	return (error);
 }
 
+#ifdef __CHERI__
+int
+copyinptr_nofault(const void *udaddr, void *kaddr, size_t len)
+{
+	int error, save;
+
+	save = vm_fault_disable_pagefaults();
+	error = copyinptr(udaddr, kaddr, len);
+	vm_fault_enable_pagefaults(save);
+	return (error);
+}
+
+int
+copyoutptr_nofault(const void *kaddr, void *udaddr, size_t len)
+{
+	int error, save;
+
+	save = vm_fault_disable_pagefaults();
+	error = copyoutptr(kaddr, udaddr, len);
+	vm_fault_enable_pagefaults(save);
+	return (error);
+}
+#endif
+
 #define	PHYS_PAGE_COUNT(len)	(howmany(len, PAGE_SIZE) + 1)
 
 int
diff --git a/sys/sys/systm.h b/sys/sys/systm.h
index e50b02bfb7cf..f2c5051ac03d 100644
--- a/sys/sys/systm.h
+++ b/sys/sys/systm.h
@@ -313,6 +313,24 @@ __nodiscard int copyout_nofault(
     const void * _Nonnull __restrict kaddr, void * __restrict udaddr,
     size_t len);
 
+#ifdef __CHERI__
+__nodiscard int copyinptr(const void * __restrict udaddr,
+    void * _Nonnull __restrict kaddr, size_t len);
+__nodiscard int copyinptr_nofault(const void * __restrict udaddr,
+    void * _Nonnull __restrict kaddr, size_t len);
+__nodiscard int copyoutptr(
+    const void * _Nonnull __restrict kaddr, void * __restrict udaddr,
+    size_t len);
+__nodiscard int copyoutptr_nofault(
+    const void * _Nonnull __restrict kaddr, void * __restrict udaddr,
+    size_t len);
+#else
+#define	copyinptr		copyin
+#define	copyinptr_nofault	copyin_nofault
+#define	copyoutptr		copyout
+#define	copyoutptr_nofault	copyout_nofault
+#endif
+
 #ifdef SAN_NEEDS_INTERCEPTORS
 int	SAN_INTERCEPTOR(copyin)(const void *, void *, size_t);
 int	SAN_INTERCEPTOR(copyinstr)(const void *, void *, size_t, size_t *);