mirror of
https://github.com/freebsd/freebsd-src.git
synced 2026-11-07 04:36:52 -10:00
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
This commit is contained in:
1 parent
bbc2d15857
commit
b517edb8de
3 files changed
+86
-5
No files matched your search
+44
-5
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
Reference in new issue
Block a user