linux_io/
ptr.rs

1/// A pointer to readable userspace memory with a defined in-memory representation.
2///
3/// This exists primarily for use in defining safe `ioctl`/etc request types,
4/// to ensure that only valid addresses can be assigned to a field from
5/// safe Rust.
6///
7/// If a struct type used with an ioctl request has a field containing an
8/// address that the kernel only reads from then defining that field as
9/// a `UserPtr` ensures that it can only have a valid address assigned
10/// to it unless the caller uses the unsafe [`Self::from_ptr`].
11///
12/// The in-memory representation of this type is guaranteed to match
13/// that of type parameter `R`, which defaults to being a pointer to `T`.
14#[repr(transparent)]
15pub struct UserPtr<'a, T: Sized, R: Copy + Repr<T> = *const T> {
16    v: R,
17    _phantom: core::marker::PhantomData<&'a T>,
18}
19
20impl<'a, T: Sized, R: Copy + Repr<T>> UserPtr<'a, T, R> {
21    /// Create a representation of the given pointer.
22    ///
23    /// # Safety
24    ///
25    /// The pointer must remain valid for the lifetime of the result.
26    #[inline(always)]
27    pub unsafe fn from_ptr(ptr: *const T) -> Self {
28        Self {
29            v: R::from_ptr(ptr),
30            _phantom: core::marker::PhantomData,
31        }
32    }
33
34    /// Create a representation of a pointer referring to the same object
35    /// as the given reference.
36    #[inline(always)]
37    pub fn from_ref(r: &'a T) -> Self {
38        let ptr = r as *const _;
39        unsafe { Self::from_ptr(ptr) }
40    }
41
42    /// Get the in-memory representation of the pointer.
43    #[inline(always)]
44    pub fn repr(&self) -> R {
45        self.v
46    }
47}
48
49/// A pointer to mutable userspace memory with a defined in-memory representation.
50///
51/// This exists primarily for use in defining safe `ioctl`/etc request types,
52/// to ensure that only valid addresses can be assigned to a field from
53/// safe Rust. Using this is important for any pointer that the kernel might
54/// write through, to ensure that safe Rust cannot assign an address that
55/// might cause the kernel to corrupt memory.
56///
57/// If a struct type used with an ioctl request has a field containing an
58/// address that the kernel might write to then defining that field as
59/// a `UserPtr` ensures that it can only have a valid address assigned
60/// to it unless the caller uses the unsafe [`Self::from_ptr`].
61///
62/// The in-memory representation of this type is guaranteed to match
63/// that of type parameter `R`, which defaults to being a pointer to `T`.
64#[repr(transparent)]
65pub struct UserMut<'a, T: Sized, R: Copy + ReprMut<T> = *mut T> {
66    v: R,
67    _phantom: core::marker::PhantomData<&'a mut T>,
68}
69
70impl<'a, T: Sized, R: Copy + ReprMut<T>> UserMut<'a, T, R> {
71    /// Create a representation of the given pointer.
72    ///
73    /// # Safety
74    ///
75    /// The pointer must remain valid for the lifetime of the result.
76    #[inline(always)]
77    pub unsafe fn from_ptr(ptr: *mut T) -> Self {
78        Self {
79            v: R::from_mut_ptr(ptr),
80            _phantom: core::marker::PhantomData,
81        }
82    }
83
84    /// Create a representation of a pointer referring to the same object
85    /// as the given reference.
86    #[inline(always)]
87    pub fn from_ref(r: &'a mut T) -> Self {
88        let ptr = r as *mut _;
89        unsafe { Self::from_ptr(ptr) }
90    }
91
92    /// Get the in-memory representation of the pointer.
93    #[inline(always)]
94    pub fn repr(&self) -> R {
95        self.v
96    }
97}
98
99/// Trait implemented by types that can represent readable userspace addresses.
100pub unsafe trait Repr<T> {
101    /// Convert the given pointer to the implementing type, without
102    /// losing any information that the kernel would need to treat
103    /// the result as a userspace pointer to the same address.
104    fn from_ptr(ptr: *const T) -> Self;
105}
106
107/// Trait implemented by types that can represent writable userspace addresses.
108pub unsafe trait ReprMut<T> {
109    /// Convert the given pointer to the implementing type, without
110    /// losing any information that the kernel would need to treat
111    /// the result as a userspace pointer to the same address.
112    fn from_mut_ptr(ptr: *mut T) -> Self;
113}
114
115unsafe impl<T> Repr<T> for *const T {
116    #[inline(always)]
117    fn from_ptr(ptr: *const T) -> Self {
118        ptr
119    }
120}
121
122unsafe impl<T> ReprMut<T> for *mut T {
123    #[inline(always)]
124    fn from_mut_ptr(ptr: *mut T) -> Self {
125        ptr as *mut T
126    }
127}
128
129unsafe impl<T> Repr<T> for u64 {
130    #[inline(always)]
131    fn from_ptr(ptr: *const T) -> Self {
132        ptr as u64
133    }
134}
135
136unsafe impl<T> ReprMut<T> for u64 {
137    #[inline(always)]
138    fn from_mut_ptr(ptr: *mut T) -> Self {
139        ptr as u64
140    }
141}
142
143unsafe impl<T> Repr<T> for usize {
144    #[inline(always)]
145    fn from_ptr(ptr: *const T) -> Self {
146        ptr as usize
147    }
148}
149
150unsafe impl<T> ReprMut<T> for usize {
151    #[inline(always)]
152    fn from_mut_ptr(ptr: *mut T) -> Self {
153        ptr as usize
154    }
155}
156
157#[cfg(test)]
158#[allow(dead_code, unused_variables)]
159pub fn ensure_reprs_possible() {
160    // This is here just as a set of static assertions to ensure that
161    // some commonly-needed patterns remain possible.
162
163    let ptr: UserPtr<u8> = UserPtr::from_ref(&0_u8);
164    let ptr: UserPtr<u8, *const u8> = UserPtr::from_ref(&0_u8);
165    let ptr: UserPtr<u8, u64> = UserPtr::from_ref(&0_u8);
166    let ptr: UserPtr<u8, usize> = UserPtr::from_ref(&0_u8);
167
168    let ptr: UserMut<u8> = UserMut::from_ref(&mut 0_u8);
169    let ptr: UserMut<u8, *mut u8> = UserMut::from_ref(&mut 0_u8);
170    let ptr: UserMut<u8, u64> = UserMut::from_ref(&mut 0_u8);
171    let ptr: UserMut<u8, usize> = UserMut::from_ref(&mut 0_u8);
172}