/// A pointer to readable userspace memory with a defined in-memory representation. /// /// This exists primarily for use in defining safe `ioctl`/etc request types, /// to ensure that only valid addresses can be assigned to a field from /// safe Rust. /// /// If a struct type used with an ioctl request has a field containing an /// address that the kernel only reads from then defining that field as /// a `UserPtr` ensures that it can only have a valid address assigned /// to it unless the caller uses the unsafe [`Self::from_ptr`]. /// /// The in-memory representation of this type is guaranteed to match /// that of type parameter `R`, which defaults to being a pointer to `T`. #[repr(transparent)] pub struct UserPtr<'a, T: Sized, R: Copy + Repr = *const T> { v: R, _phantom: core::marker::PhantomData<&'a T>, } impl<'a, T: Sized, R: Copy + Repr> UserPtr<'a, T, R> { /// Create a representation of the given pointer. /// /// # Safety /// /// The pointer must remain valid for the lifetime of the result. #[inline(always)] pub unsafe fn from_ptr(ptr: *const T) -> Self { Self { v: R::from_ptr(ptr), _phantom: core::marker::PhantomData, } } /// Create a representation of a pointer referring to the same object /// as the given reference. #[inline(always)] pub fn from_ref(r: &'a T) -> Self { let ptr = r as *const _; unsafe { Self::from_ptr(ptr) } } /// Get the in-memory representation of the pointer. #[inline(always)] pub fn repr(&self) -> R { self.v } } /// A pointer to mutable userspace memory with a defined in-memory representation. /// /// This exists primarily for use in defining safe `ioctl`/etc request types, /// to ensure that only valid addresses can be assigned to a field from /// safe Rust. Using this is important for any pointer that the kernel might /// write through, to ensure that safe Rust cannot assign an address that /// might cause the kernel to corrupt memory. /// /// If a struct type used with an ioctl request has a field containing an /// address that the kernel might write to then defining that field as /// a `UserPtr` ensures that it can only have a valid address assigned /// to it unless the caller uses the unsafe [`Self::from_ptr`]. /// /// The in-memory representation of this type is guaranteed to match /// that of type parameter `R`, which defaults to being a pointer to `T`. #[repr(transparent)] pub struct UserMut<'a, T: Sized, R: Copy + ReprMut = *mut T> { v: R, _phantom: core::marker::PhantomData<&'a mut T>, } impl<'a, T: Sized, R: Copy + ReprMut> UserMut<'a, T, R> { /// Create a representation of the given pointer. /// /// # Safety /// /// The pointer must remain valid for the lifetime of the result. #[inline(always)] pub unsafe fn from_ptr(ptr: *mut T) -> Self { Self { v: R::from_mut_ptr(ptr), _phantom: core::marker::PhantomData, } } /// Create a representation of a pointer referring to the same object /// as the given reference. #[inline(always)] pub fn from_ref(r: &'a mut T) -> Self { let ptr = r as *mut _; unsafe { Self::from_ptr(ptr) } } /// Get the in-memory representation of the pointer. #[inline(always)] pub fn repr(&self) -> R { self.v } } /// Trait implemented by types that can represent readable userspace addresses. pub unsafe trait Repr { /// Convert the given pointer to the implementing type, without /// losing any information that the kernel would need to treat /// the result as a userspace pointer to the same address. fn from_ptr(ptr: *const T) -> Self; } /// Trait implemented by types that can represent writable userspace addresses. pub unsafe trait ReprMut { /// Convert the given pointer to the implementing type, without /// losing any information that the kernel would need to treat /// the result as a userspace pointer to the same address. fn from_mut_ptr(ptr: *mut T) -> Self; } unsafe impl Repr for *const T { #[inline(always)] fn from_ptr(ptr: *const T) -> Self { ptr } } unsafe impl ReprMut for *mut T { #[inline(always)] fn from_mut_ptr(ptr: *mut T) -> Self { ptr as *mut T } } unsafe impl Repr for u64 { #[inline(always)] fn from_ptr(ptr: *const T) -> Self { ptr as u64 } } unsafe impl ReprMut for u64 { #[inline(always)] fn from_mut_ptr(ptr: *mut T) -> Self { ptr as u64 } } unsafe impl Repr for usize { #[inline(always)] fn from_ptr(ptr: *const T) -> Self { ptr as usize } } unsafe impl ReprMut for usize { #[inline(always)] fn from_mut_ptr(ptr: *mut T) -> Self { ptr as usize } } #[cfg(test)] #[allow(dead_code, unused_variables)] pub fn ensure_reprs_possible() { // This is here just as a set of static assertions to ensure that // some commonly-needed patterns remain possible. let ptr: UserPtr = UserPtr::from_ref(&0_u8); let ptr: UserPtr = UserPtr::from_ref(&0_u8); let ptr: UserPtr = UserPtr::from_ref(&0_u8); let ptr: UserPtr = UserPtr::from_ref(&0_u8); let ptr: UserMut = UserMut::from_ref(&mut 0_u8); let ptr: UserMut = UserMut::from_ref(&mut 0_u8); let ptr: UserMut = UserMut::from_ref(&mut 0_u8); let ptr: UserMut = UserMut::from_ref(&mut 0_u8); }