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}