1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
/// 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<T> = *const T> {
v: R,
_phantom: core::marker::PhantomData<&'a T>,
}
impl<'a, T: Sized, R: Copy + Repr<T>> 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<T> = *mut T> {
v: R,
_phantom: core::marker::PhantomData<&'a mut T>,
}
impl<'a, T: Sized, R: Copy + ReprMut<T>> 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<T> {
/// 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<T> {
/// 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<T> Repr<T> for *const T {
#[inline(always)]
fn from_ptr(ptr: *const T) -> Self {
ptr
}
}
unsafe impl<T> ReprMut<T> for *mut T {
#[inline(always)]
fn from_mut_ptr(ptr: *mut T) -> Self {
ptr as *mut T
}
}
unsafe impl<T> Repr<T> for u64 {
#[inline(always)]
fn from_ptr(ptr: *const T) -> Self {
ptr as u64
}
}
unsafe impl<T> ReprMut<T> for u64 {
#[inline(always)]
fn from_mut_ptr(ptr: *mut T) -> Self {
ptr as u64
}
}
unsafe impl<T> Repr<T> for usize {
#[inline(always)]
fn from_ptr(ptr: *const T) -> Self {
ptr as usize
}
}
unsafe impl<T> ReprMut<T> 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<u8> = UserPtr::from_ref(&0_u8);
let ptr: UserPtr<u8, *const u8> = UserPtr::from_ref(&0_u8);
let ptr: UserPtr<u8, u64> = UserPtr::from_ref(&0_u8);
let ptr: UserPtr<u8, usize> = UserPtr::from_ref(&0_u8);
let ptr: UserMut<u8> = UserMut::from_ref(&mut 0_u8);
let ptr: UserMut<u8, *mut u8> = UserMut::from_ref(&mut 0_u8);
let ptr: UserMut<u8, u64> = UserMut::from_ref(&mut 0_u8);
let ptr: UserMut<u8, usize> = UserMut::from_ref(&mut 0_u8);
}