11b580e7bSWedson Almeida Filho // SPDX-License-Identifier: GPL-2.0 21b580e7bSWedson Almeida Filho 31b580e7bSWedson Almeida Filho //! Slices to user space memory regions. 41b580e7bSWedson Almeida Filho //! 51b580e7bSWedson Almeida Filho //! C header: [`include/linux/uaccess.h`](srctree/include/linux/uaccess.h) 61b580e7bSWedson Almeida Filho 7b33bf37aSAlice Ryhl use crate::{ 8c80dd3fcSFilipe Xavier alloc::{Allocator, Flags}, 9b33bf37aSAlice Ryhl bindings, 10b33bf37aSAlice Ryhl error::Result, 111bae8729SGary Guo ffi::c_void, 12b33bf37aSAlice Ryhl prelude::*, 13ce1c54fdSAliet Exposito Garcia transmute::{AsBytes, FromBytes}, 14b33bf37aSAlice Ryhl }; 15b33bf37aSAlice Ryhl use core::mem::{size_of, MaybeUninit}; 161b580e7bSWedson Almeida Filho 171b580e7bSWedson Almeida Filho /// The type used for userspace addresses. 181b580e7bSWedson Almeida Filho pub type UserPtr = usize; 191b580e7bSWedson Almeida Filho 201b580e7bSWedson Almeida Filho /// A pointer to an area in userspace memory, which can be either read-only or read-write. 211b580e7bSWedson Almeida Filho /// 221b580e7bSWedson Almeida Filho /// All methods on this struct are safe: attempting to read or write on bad addresses (either out of 231b580e7bSWedson Almeida Filho /// the bound of the slice or unmapped addresses) will return [`EFAULT`]. Concurrent access, 241b580e7bSWedson Almeida Filho /// *including data races to/from userspace memory*, is permitted, because fundamentally another 251b580e7bSWedson Almeida Filho /// userspace thread/process could always be modifying memory at the same time (in the same way that 261b580e7bSWedson Almeida Filho /// userspace Rust's [`std::io`] permits data races with the contents of files on disk). In the 271b580e7bSWedson Almeida Filho /// presence of a race, the exact byte values read/written are unspecified but the operation is 281b580e7bSWedson Almeida Filho /// well-defined. Kernelspace code should validate its copy of data after completing a read, and not 291b580e7bSWedson Almeida Filho /// expect that multiple reads of the same address will return the same value. 301b580e7bSWedson Almeida Filho /// 311b580e7bSWedson Almeida Filho /// These APIs are designed to make it difficult to accidentally write TOCTOU (time-of-check to 321b580e7bSWedson Almeida Filho /// time-of-use) bugs. Every time a memory location is read, the reader's position is advanced by 331b580e7bSWedson Almeida Filho /// the read length and the next read will start from there. This helps prevent accidentally reading 341b580e7bSWedson Almeida Filho /// the same location twice and causing a TOCTOU bug. 351b580e7bSWedson Almeida Filho /// 361b580e7bSWedson Almeida Filho /// Creating a [`UserSliceReader`] and/or [`UserSliceWriter`] consumes the `UserSlice`, helping 371b580e7bSWedson Almeida Filho /// ensure that there aren't multiple readers or writers to the same location. 381b580e7bSWedson Almeida Filho /// 391b580e7bSWedson Almeida Filho /// If double-fetching a memory location is necessary for some reason, then that is done by creating 401b580e7bSWedson Almeida Filho /// multiple readers to the same memory location, e.g. using [`clone_reader`]. 411b580e7bSWedson Almeida Filho /// 421b580e7bSWedson Almeida Filho /// # Examples 431b580e7bSWedson Almeida Filho /// 441b580e7bSWedson Almeida Filho /// Takes a region of userspace memory from the current process, and modify it by adding one to 451b580e7bSWedson Almeida Filho /// every byte in the region. 461b580e7bSWedson Almeida Filho /// 471b580e7bSWedson Almeida Filho /// ```no_run 48d072acdaSGary Guo /// use kernel::ffi::c_void; 491b580e7bSWedson Almeida Filho /// use kernel::error::Result; 501b580e7bSWedson Almeida Filho /// use kernel::uaccess::{UserPtr, UserSlice}; 511b580e7bSWedson Almeida Filho /// 521b580e7bSWedson Almeida Filho /// fn bytes_add_one(uptr: UserPtr, len: usize) -> Result<()> { 531b580e7bSWedson Almeida Filho /// let (read, mut write) = UserSlice::new(uptr, len).reader_writer(); 541b580e7bSWedson Almeida Filho /// 5558eff8e8SDanilo Krummrich /// let mut buf = KVec::new(); 561b580e7bSWedson Almeida Filho /// read.read_all(&mut buf, GFP_KERNEL)?; 571b580e7bSWedson Almeida Filho /// 581b580e7bSWedson Almeida Filho /// for b in &mut buf { 591b580e7bSWedson Almeida Filho /// *b = b.wrapping_add(1); 601b580e7bSWedson Almeida Filho /// } 611b580e7bSWedson Almeida Filho /// 621b580e7bSWedson Almeida Filho /// write.write_slice(&buf)?; 631b580e7bSWedson Almeida Filho /// Ok(()) 641b580e7bSWedson Almeida Filho /// } 651b580e7bSWedson Almeida Filho /// ``` 661b580e7bSWedson Almeida Filho /// 671b580e7bSWedson Almeida Filho /// Example illustrating a TOCTOU (time-of-check to time-of-use) bug. 681b580e7bSWedson Almeida Filho /// 691b580e7bSWedson Almeida Filho /// ```no_run 70d072acdaSGary Guo /// use kernel::ffi::c_void; 711b580e7bSWedson Almeida Filho /// use kernel::error::{code::EINVAL, Result}; 721b580e7bSWedson Almeida Filho /// use kernel::uaccess::{UserPtr, UserSlice}; 731b580e7bSWedson Almeida Filho /// 741b580e7bSWedson Almeida Filho /// /// Returns whether the data in this region is valid. 751b580e7bSWedson Almeida Filho /// fn is_valid(uptr: UserPtr, len: usize) -> Result<bool> { 761b580e7bSWedson Almeida Filho /// let read = UserSlice::new(uptr, len).reader(); 771b580e7bSWedson Almeida Filho /// 7858eff8e8SDanilo Krummrich /// let mut buf = KVec::new(); 791b580e7bSWedson Almeida Filho /// read.read_all(&mut buf, GFP_KERNEL)?; 801b580e7bSWedson Almeida Filho /// 811b580e7bSWedson Almeida Filho /// todo!() 821b580e7bSWedson Almeida Filho /// } 831b580e7bSWedson Almeida Filho /// 841b580e7bSWedson Almeida Filho /// /// Returns the bytes behind this user pointer if they are valid. 8558eff8e8SDanilo Krummrich /// fn get_bytes_if_valid(uptr: UserPtr, len: usize) -> Result<KVec<u8>> { 861b580e7bSWedson Almeida Filho /// if !is_valid(uptr, len)? { 871b580e7bSWedson Almeida Filho /// return Err(EINVAL); 881b580e7bSWedson Almeida Filho /// } 891b580e7bSWedson Almeida Filho /// 901b580e7bSWedson Almeida Filho /// let read = UserSlice::new(uptr, len).reader(); 911b580e7bSWedson Almeida Filho /// 9258eff8e8SDanilo Krummrich /// let mut buf = KVec::new(); 931b580e7bSWedson Almeida Filho /// read.read_all(&mut buf, GFP_KERNEL)?; 941b580e7bSWedson Almeida Filho /// 951b580e7bSWedson Almeida Filho /// // THIS IS A BUG! The bytes could have changed since we checked them. 961b580e7bSWedson Almeida Filho /// // 971b580e7bSWedson Almeida Filho /// // To avoid this kind of bug, don't call `UserSlice::new` multiple 981b580e7bSWedson Almeida Filho /// // times with the same address. 991b580e7bSWedson Almeida Filho /// Ok(buf) 1001b580e7bSWedson Almeida Filho /// } 1011b580e7bSWedson Almeida Filho /// ``` 1021b580e7bSWedson Almeida Filho /// 1031b580e7bSWedson Almeida Filho /// [`std::io`]: https://doc.rust-lang.org/std/io/index.html 1041b580e7bSWedson Almeida Filho /// [`clone_reader`]: UserSliceReader::clone_reader 1051b580e7bSWedson Almeida Filho pub struct UserSlice { 1061b580e7bSWedson Almeida Filho ptr: UserPtr, 1071b580e7bSWedson Almeida Filho length: usize, 1081b580e7bSWedson Almeida Filho } 1091b580e7bSWedson Almeida Filho 1101b580e7bSWedson Almeida Filho impl UserSlice { 1111b580e7bSWedson Almeida Filho /// Constructs a user slice from a raw pointer and a length in bytes. 1121b580e7bSWedson Almeida Filho /// 1131b580e7bSWedson Almeida Filho /// Constructing a [`UserSlice`] performs no checks on the provided address and length, it can 1141b580e7bSWedson Almeida Filho /// safely be constructed inside a kernel thread with no current userspace process. Reads and 1151b580e7bSWedson Almeida Filho /// writes wrap the kernel APIs `copy_from_user` and `copy_to_user`, which check the memory map 1161b580e7bSWedson Almeida Filho /// of the current process and enforce that the address range is within the user range (no 1171b580e7bSWedson Almeida Filho /// additional calls to `access_ok` are needed). Validity of the pointer is checked when you 1181b580e7bSWedson Almeida Filho /// attempt to read or write, not in the call to `UserSlice::new`. 1191b580e7bSWedson Almeida Filho /// 1201b580e7bSWedson Almeida Filho /// Callers must be careful to avoid time-of-check-time-of-use (TOCTOU) issues. The simplest way 1211b580e7bSWedson Almeida Filho /// is to create a single instance of [`UserSlice`] per user memory block as it reads each byte 1221b580e7bSWedson Almeida Filho /// at most once. new(ptr: UserPtr, length: usize) -> Self1231b580e7bSWedson Almeida Filho pub fn new(ptr: UserPtr, length: usize) -> Self { 1241b580e7bSWedson Almeida Filho UserSlice { ptr, length } 1251b580e7bSWedson Almeida Filho } 1261b580e7bSWedson Almeida Filho 1271b580e7bSWedson Almeida Filho /// Reads the entirety of the user slice, appending it to the end of the provided buffer. 1281b580e7bSWedson Almeida Filho /// 1291b580e7bSWedson Almeida Filho /// Fails with [`EFAULT`] if the read happens on a bad address. read_all<A: Allocator>(self, buf: &mut Vec<u8, A>, flags: Flags) -> Result130c80dd3fcSFilipe Xavier pub fn read_all<A: Allocator>(self, buf: &mut Vec<u8, A>, flags: Flags) -> Result { 1311b580e7bSWedson Almeida Filho self.reader().read_all(buf, flags) 1321b580e7bSWedson Almeida Filho } 1331b580e7bSWedson Almeida Filho 1341b580e7bSWedson Almeida Filho /// Constructs a [`UserSliceReader`]. reader(self) -> UserSliceReader1351b580e7bSWedson Almeida Filho pub fn reader(self) -> UserSliceReader { 1361b580e7bSWedson Almeida Filho UserSliceReader { 1371b580e7bSWedson Almeida Filho ptr: self.ptr, 1381b580e7bSWedson Almeida Filho length: self.length, 1391b580e7bSWedson Almeida Filho } 1401b580e7bSWedson Almeida Filho } 1411b580e7bSWedson Almeida Filho 1421b580e7bSWedson Almeida Filho /// Constructs a [`UserSliceWriter`]. writer(self) -> UserSliceWriter1431b580e7bSWedson Almeida Filho pub fn writer(self) -> UserSliceWriter { 1441b580e7bSWedson Almeida Filho UserSliceWriter { 1451b580e7bSWedson Almeida Filho ptr: self.ptr, 1461b580e7bSWedson Almeida Filho length: self.length, 1471b580e7bSWedson Almeida Filho } 1481b580e7bSWedson Almeida Filho } 1491b580e7bSWedson Almeida Filho 1501b580e7bSWedson Almeida Filho /// Constructs both a [`UserSliceReader`] and a [`UserSliceWriter`]. 1511b580e7bSWedson Almeida Filho /// 1521b580e7bSWedson Almeida Filho /// Usually when this is used, you will first read the data, and then overwrite it afterwards. reader_writer(self) -> (UserSliceReader, UserSliceWriter)1531b580e7bSWedson Almeida Filho pub fn reader_writer(self) -> (UserSliceReader, UserSliceWriter) { 1541b580e7bSWedson Almeida Filho ( 1551b580e7bSWedson Almeida Filho UserSliceReader { 1561b580e7bSWedson Almeida Filho ptr: self.ptr, 1571b580e7bSWedson Almeida Filho length: self.length, 1581b580e7bSWedson Almeida Filho }, 1591b580e7bSWedson Almeida Filho UserSliceWriter { 1601b580e7bSWedson Almeida Filho ptr: self.ptr, 1611b580e7bSWedson Almeida Filho length: self.length, 1621b580e7bSWedson Almeida Filho }, 1631b580e7bSWedson Almeida Filho ) 1641b580e7bSWedson Almeida Filho } 1651b580e7bSWedson Almeida Filho } 1661b580e7bSWedson Almeida Filho 1671b580e7bSWedson Almeida Filho /// A reader for [`UserSlice`]. 1681b580e7bSWedson Almeida Filho /// 1691b580e7bSWedson Almeida Filho /// Used to incrementally read from the user slice. 1701b580e7bSWedson Almeida Filho pub struct UserSliceReader { 1711b580e7bSWedson Almeida Filho ptr: UserPtr, 1721b580e7bSWedson Almeida Filho length: usize, 1731b580e7bSWedson Almeida Filho } 1741b580e7bSWedson Almeida Filho 1751b580e7bSWedson Almeida Filho impl UserSliceReader { 1761b580e7bSWedson Almeida Filho /// Skip the provided number of bytes. 1771b580e7bSWedson Almeida Filho /// 1781b580e7bSWedson Almeida Filho /// Returns an error if skipping more than the length of the buffer. skip(&mut self, num_skip: usize) -> Result1791b580e7bSWedson Almeida Filho pub fn skip(&mut self, num_skip: usize) -> Result { 1801b580e7bSWedson Almeida Filho // Update `self.length` first since that's the fallible part of this operation. 1811b580e7bSWedson Almeida Filho self.length = self.length.checked_sub(num_skip).ok_or(EFAULT)?; 1821b580e7bSWedson Almeida Filho self.ptr = self.ptr.wrapping_add(num_skip); 1831b580e7bSWedson Almeida Filho Ok(()) 1841b580e7bSWedson Almeida Filho } 1851b580e7bSWedson Almeida Filho 1861b580e7bSWedson Almeida Filho /// Create a reader that can access the same range of data. 1871b580e7bSWedson Almeida Filho /// 1881b580e7bSWedson Almeida Filho /// Reading from the clone does not advance the current reader. 1891b580e7bSWedson Almeida Filho /// 1901b580e7bSWedson Almeida Filho /// The caller should take care to not introduce TOCTOU issues, as described in the 1911b580e7bSWedson Almeida Filho /// documentation for [`UserSlice`]. clone_reader(&self) -> UserSliceReader1921b580e7bSWedson Almeida Filho pub fn clone_reader(&self) -> UserSliceReader { 1931b580e7bSWedson Almeida Filho UserSliceReader { 1941b580e7bSWedson Almeida Filho ptr: self.ptr, 1951b580e7bSWedson Almeida Filho length: self.length, 1961b580e7bSWedson Almeida Filho } 1971b580e7bSWedson Almeida Filho } 1981b580e7bSWedson Almeida Filho 1991b580e7bSWedson Almeida Filho /// Returns the number of bytes left to be read from this reader. 2001b580e7bSWedson Almeida Filho /// 2011b580e7bSWedson Almeida Filho /// Note that even reading less than this number of bytes may fail. len(&self) -> usize2021b580e7bSWedson Almeida Filho pub fn len(&self) -> usize { 2031b580e7bSWedson Almeida Filho self.length 2041b580e7bSWedson Almeida Filho } 2051b580e7bSWedson Almeida Filho 2061b580e7bSWedson Almeida Filho /// Returns `true` if no data is available in the io buffer. is_empty(&self) -> bool2071b580e7bSWedson Almeida Filho pub fn is_empty(&self) -> bool { 2081b580e7bSWedson Almeida Filho self.length == 0 2091b580e7bSWedson Almeida Filho } 2101b580e7bSWedson Almeida Filho 2111b580e7bSWedson Almeida Filho /// Reads raw data from the user slice into a kernel buffer. 2121b580e7bSWedson Almeida Filho /// 2131b580e7bSWedson Almeida Filho /// For a version that uses `&mut [u8]`, please see [`UserSliceReader::read_slice`]. 2141b580e7bSWedson Almeida Filho /// 2151b580e7bSWedson Almeida Filho /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of 2161b580e7bSWedson Almeida Filho /// bounds of this [`UserSliceReader`]. This call may modify `out` even if it returns an error. 2171b580e7bSWedson Almeida Filho /// 2181b580e7bSWedson Almeida Filho /// # Guarantees 2191b580e7bSWedson Almeida Filho /// 2201b580e7bSWedson Almeida Filho /// After a successful call to this method, all bytes in `out` are initialized. read_raw(&mut self, out: &mut [MaybeUninit<u8>]) -> Result2211b580e7bSWedson Almeida Filho pub fn read_raw(&mut self, out: &mut [MaybeUninit<u8>]) -> Result { 2221b580e7bSWedson Almeida Filho let len = out.len(); 2231b580e7bSWedson Almeida Filho let out_ptr = out.as_mut_ptr().cast::<c_void>(); 2241b580e7bSWedson Almeida Filho if len > self.length { 2251b580e7bSWedson Almeida Filho return Err(EFAULT); 2261b580e7bSWedson Almeida Filho } 2271bae8729SGary Guo // SAFETY: `out_ptr` points into a mutable slice of length `len`, so we may write 2281b580e7bSWedson Almeida Filho // that many bytes to it. 2291bae8729SGary Guo let res = unsafe { bindings::copy_from_user(out_ptr, self.ptr as *const c_void, len) }; 2301b580e7bSWedson Almeida Filho if res != 0 { 2311b580e7bSWedson Almeida Filho return Err(EFAULT); 2321b580e7bSWedson Almeida Filho } 2331b580e7bSWedson Almeida Filho self.ptr = self.ptr.wrapping_add(len); 2341b580e7bSWedson Almeida Filho self.length -= len; 2351b580e7bSWedson Almeida Filho Ok(()) 2361b580e7bSWedson Almeida Filho } 2371b580e7bSWedson Almeida Filho 2381b580e7bSWedson Almeida Filho /// Reads raw data from the user slice into a kernel buffer. 2391b580e7bSWedson Almeida Filho /// 2401b580e7bSWedson Almeida Filho /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of 2411b580e7bSWedson Almeida Filho /// bounds of this [`UserSliceReader`]. This call may modify `out` even if it returns an error. read_slice(&mut self, out: &mut [u8]) -> Result2421b580e7bSWedson Almeida Filho pub fn read_slice(&mut self, out: &mut [u8]) -> Result { 2431b580e7bSWedson Almeida Filho // SAFETY: The types are compatible and `read_raw` doesn't write uninitialized bytes to 2441b580e7bSWedson Almeida Filho // `out`. 2451b580e7bSWedson Almeida Filho let out = unsafe { &mut *(out as *mut [u8] as *mut [MaybeUninit<u8>]) }; 2461b580e7bSWedson Almeida Filho self.read_raw(out) 2471b580e7bSWedson Almeida Filho } 2481b580e7bSWedson Almeida Filho 249b33bf37aSAlice Ryhl /// Reads a value of the specified type. 250b33bf37aSAlice Ryhl /// 251b33bf37aSAlice Ryhl /// Fails with [`EFAULT`] if the read happens on a bad address, or if the read goes out of 252b33bf37aSAlice Ryhl /// bounds of this [`UserSliceReader`]. read<T: FromBytes>(&mut self) -> Result<T>253b33bf37aSAlice Ryhl pub fn read<T: FromBytes>(&mut self) -> Result<T> { 254b33bf37aSAlice Ryhl let len = size_of::<T>(); 255b33bf37aSAlice Ryhl if len > self.length { 256b33bf37aSAlice Ryhl return Err(EFAULT); 257b33bf37aSAlice Ryhl } 258b33bf37aSAlice Ryhl let mut out: MaybeUninit<T> = MaybeUninit::uninit(); 259b33bf37aSAlice Ryhl // SAFETY: The local variable `out` is valid for writing `size_of::<T>()` bytes. 260b33bf37aSAlice Ryhl // 261b33bf37aSAlice Ryhl // By using the _copy_from_user variant, we skip the check_object_size check that verifies 262b33bf37aSAlice Ryhl // the kernel pointer. This mirrors the logic on the C side that skips the check when the 263b33bf37aSAlice Ryhl // length is a compile-time constant. 264b33bf37aSAlice Ryhl let res = unsafe { 265b33bf37aSAlice Ryhl bindings::_copy_from_user( 266b33bf37aSAlice Ryhl out.as_mut_ptr().cast::<c_void>(), 267b33bf37aSAlice Ryhl self.ptr as *const c_void, 2681bae8729SGary Guo len, 269b33bf37aSAlice Ryhl ) 270b33bf37aSAlice Ryhl }; 271b33bf37aSAlice Ryhl if res != 0 { 272b33bf37aSAlice Ryhl return Err(EFAULT); 273b33bf37aSAlice Ryhl } 274b33bf37aSAlice Ryhl self.ptr = self.ptr.wrapping_add(len); 275b33bf37aSAlice Ryhl self.length -= len; 276b33bf37aSAlice Ryhl // SAFETY: The read above has initialized all bytes in `out`, and since `T` implements 277b33bf37aSAlice Ryhl // `FromBytes`, any bit-pattern is a valid value for this type. 278b33bf37aSAlice Ryhl Ok(unsafe { out.assume_init() }) 279b33bf37aSAlice Ryhl } 280b33bf37aSAlice Ryhl 2811b580e7bSWedson Almeida Filho /// Reads the entirety of the user slice, appending it to the end of the provided buffer. 2821b580e7bSWedson Almeida Filho /// 2831b580e7bSWedson Almeida Filho /// Fails with [`EFAULT`] if the read happens on a bad address. read_all<A: Allocator>(mut self, buf: &mut Vec<u8, A>, flags: Flags) -> Result284c80dd3fcSFilipe Xavier pub fn read_all<A: Allocator>(mut self, buf: &mut Vec<u8, A>, flags: Flags) -> Result { 2851b580e7bSWedson Almeida Filho let len = self.length; 28658eff8e8SDanilo Krummrich buf.reserve(len, flags)?; 2871b580e7bSWedson Almeida Filho 288*4e72a62eSTamir Duberstein // The call to `reserve` was successful, so the spare capacity is at least `len` bytes long. 2891b580e7bSWedson Almeida Filho self.read_raw(&mut buf.spare_capacity_mut()[..len])?; 2901b580e7bSWedson Almeida Filho 2911b580e7bSWedson Almeida Filho // SAFETY: Since the call to `read_raw` was successful, so the next `len` bytes of the 2921b580e7bSWedson Almeida Filho // vector have been initialized. 2931b580e7bSWedson Almeida Filho unsafe { buf.set_len(buf.len() + len) }; 2941b580e7bSWedson Almeida Filho Ok(()) 2951b580e7bSWedson Almeida Filho } 2961b580e7bSWedson Almeida Filho } 2971b580e7bSWedson Almeida Filho 2981b580e7bSWedson Almeida Filho /// A writer for [`UserSlice`]. 2991b580e7bSWedson Almeida Filho /// 3001b580e7bSWedson Almeida Filho /// Used to incrementally write into the user slice. 3011b580e7bSWedson Almeida Filho pub struct UserSliceWriter { 3021b580e7bSWedson Almeida Filho ptr: UserPtr, 3031b580e7bSWedson Almeida Filho length: usize, 3041b580e7bSWedson Almeida Filho } 3051b580e7bSWedson Almeida Filho 3061b580e7bSWedson Almeida Filho impl UserSliceWriter { 3071b580e7bSWedson Almeida Filho /// Returns the amount of space remaining in this buffer. 3081b580e7bSWedson Almeida Filho /// 3091b580e7bSWedson Almeida Filho /// Note that even writing less than this number of bytes may fail. len(&self) -> usize3101b580e7bSWedson Almeida Filho pub fn len(&self) -> usize { 3111b580e7bSWedson Almeida Filho self.length 3121b580e7bSWedson Almeida Filho } 3131b580e7bSWedson Almeida Filho 3141b580e7bSWedson Almeida Filho /// Returns `true` if no more data can be written to this buffer. is_empty(&self) -> bool3151b580e7bSWedson Almeida Filho pub fn is_empty(&self) -> bool { 3161b580e7bSWedson Almeida Filho self.length == 0 3171b580e7bSWedson Almeida Filho } 3181b580e7bSWedson Almeida Filho 3191b580e7bSWedson Almeida Filho /// Writes raw data to this user pointer from a kernel buffer. 3201b580e7bSWedson Almeida Filho /// 3211b580e7bSWedson Almeida Filho /// Fails with [`EFAULT`] if the write happens on a bad address, or if the write goes out of 3221b580e7bSWedson Almeida Filho /// bounds of this [`UserSliceWriter`]. This call may modify the associated userspace slice even 3231b580e7bSWedson Almeida Filho /// if it returns an error. write_slice(&mut self, data: &[u8]) -> Result3241b580e7bSWedson Almeida Filho pub fn write_slice(&mut self, data: &[u8]) -> Result { 3251b580e7bSWedson Almeida Filho let len = data.len(); 3261b580e7bSWedson Almeida Filho let data_ptr = data.as_ptr().cast::<c_void>(); 3271b580e7bSWedson Almeida Filho if len > self.length { 3281b580e7bSWedson Almeida Filho return Err(EFAULT); 3291b580e7bSWedson Almeida Filho } 3301bae8729SGary Guo // SAFETY: `data_ptr` points into an immutable slice of length `len`, so we may read 3311b580e7bSWedson Almeida Filho // that many bytes from it. 3321bae8729SGary Guo let res = unsafe { bindings::copy_to_user(self.ptr as *mut c_void, data_ptr, len) }; 3331b580e7bSWedson Almeida Filho if res != 0 { 3341b580e7bSWedson Almeida Filho return Err(EFAULT); 3351b580e7bSWedson Almeida Filho } 3361b580e7bSWedson Almeida Filho self.ptr = self.ptr.wrapping_add(len); 3371b580e7bSWedson Almeida Filho self.length -= len; 3381b580e7bSWedson Almeida Filho Ok(()) 3391b580e7bSWedson Almeida Filho } 340b33bf37aSAlice Ryhl 341b33bf37aSAlice Ryhl /// Writes the provided Rust value to this userspace pointer. 342b33bf37aSAlice Ryhl /// 343b33bf37aSAlice Ryhl /// Fails with [`EFAULT`] if the write happens on a bad address, or if the write goes out of 344b33bf37aSAlice Ryhl /// bounds of this [`UserSliceWriter`]. This call may modify the associated userspace slice even 345b33bf37aSAlice Ryhl /// if it returns an error. write<T: AsBytes>(&mut self, value: &T) -> Result346b33bf37aSAlice Ryhl pub fn write<T: AsBytes>(&mut self, value: &T) -> Result { 347b33bf37aSAlice Ryhl let len = size_of::<T>(); 348b33bf37aSAlice Ryhl if len > self.length { 349b33bf37aSAlice Ryhl return Err(EFAULT); 350b33bf37aSAlice Ryhl } 351b33bf37aSAlice Ryhl // SAFETY: The reference points to a value of type `T`, so it is valid for reading 352b33bf37aSAlice Ryhl // `size_of::<T>()` bytes. 353b33bf37aSAlice Ryhl // 354b33bf37aSAlice Ryhl // By using the _copy_to_user variant, we skip the check_object_size check that verifies the 355b33bf37aSAlice Ryhl // kernel pointer. This mirrors the logic on the C side that skips the check when the length 356b33bf37aSAlice Ryhl // is a compile-time constant. 357b33bf37aSAlice Ryhl let res = unsafe { 358b33bf37aSAlice Ryhl bindings::_copy_to_user( 359b33bf37aSAlice Ryhl self.ptr as *mut c_void, 360b33bf37aSAlice Ryhl (value as *const T).cast::<c_void>(), 3611bae8729SGary Guo len, 362b33bf37aSAlice Ryhl ) 363b33bf37aSAlice Ryhl }; 364b33bf37aSAlice Ryhl if res != 0 { 365b33bf37aSAlice Ryhl return Err(EFAULT); 366b33bf37aSAlice Ryhl } 367b33bf37aSAlice Ryhl self.ptr = self.ptr.wrapping_add(len); 368b33bf37aSAlice Ryhl self.length -= len; 369b33bf37aSAlice Ryhl Ok(()) 370b33bf37aSAlice Ryhl } 3711b580e7bSWedson Almeida Filho } 372