Struct kernel::user_ptr::UserSlicePtr
source · [−]pub struct UserSlicePtr(_, _);
Expand description
A reference to an area in userspace memory, which can be either read-only or read-write.
All methods on this struct are safe: invalid pointers return
EFAULT
. Concurrent access, including data races to/from userspace
memory, is permitted, because fundamentally another userspace
thread/process could always be modifying memory at the same time
(in the same way that userspace Rust’s std::io
permits data races
with the contents of files on disk). In the presence of a race, the
exact byte values read/written are unspecified but the operation is
well-defined. Kernelspace code should validate its copy of data
after completing a read, and not expect that multiple reads of the
same address will return the same value.
All APIs enforce the invariant that a given byte of memory from userspace
may only be read once. By preventing double-fetches we avoid TOCTOU
vulnerabilities. This is accomplished by taking self
by value to prevent
obtaining multiple readers on a given UserSlicePtr
, and the readers
only permitting forward reads.
Constructing a UserSlicePtr
performs no checks on the provided
address and length, it can safely be constructed inside a kernel thread
with no current userspace process. Reads and writes wrap the kernel APIs
copy_from_user
and copy_to_user
, which check the memory map of the
current process and enforce that the address range is within the user
range (no additional calls to access_ok
are needed).
Implementations
sourceimpl UserSlicePtr
impl UserSlicePtr
sourcepub unsafe fn new(ptr: *mut c_void, length: usize) -> Self
pub unsafe fn new(ptr: *mut c_void, length: usize) -> Self
Constructs a user slice from a raw pointer and a length in bytes.
Safety
Callers must be careful to avoid time-of-check-time-of-use
(TOCTOU) issues. The simplest way is to create a single instance of
UserSlicePtr
per user memory block as it reads each byte at
most once.
sourcepub fn read_all(self) -> Result<Vec<u8>>
pub fn read_all(self) -> Result<Vec<u8>>
Reads the entirety of the user slice.
Returns EFAULT
if the address does not currently point to
mapped, readable memory.
sourcepub fn reader(self) -> UserSlicePtrReader
pub fn reader(self) -> UserSlicePtrReader
Constructs a UserSlicePtrReader
.
sourcepub fn write_all(self, data: &[u8]) -> Result
pub fn write_all(self, data: &[u8]) -> Result
Writes the provided slice into the user slice.
Returns EFAULT
if the address does not currently point to
mapped, writable memory (in which case some data from before the
fault may be written), or data
is larger than the user slice
(in which case no data is written).
sourcepub fn writer(self) -> UserSlicePtrWriter
pub fn writer(self) -> UserSlicePtrWriter
Constructs a UserSlicePtrWriter
.
sourcepub fn reader_writer(self) -> (UserSlicePtrReader, UserSlicePtrWriter)
pub fn reader_writer(self) -> (UserSlicePtrReader, UserSlicePtrWriter)
Constructs both a UserSlicePtrReader
and a UserSlicePtrWriter
.