1 // SPDX-License-Identifier: GPL-2.0 2 3 //! Infrastructure for handling projections. 4 5 use core::{ 6 mem::MaybeUninit, 7 ops::Deref, // 8 }; 9 10 use crate::prelude::*; 11 12 /// Error raised when a projection is attempted on an array or slice out of bounds. 13 pub struct OutOfBound; 14 15 impl From<OutOfBound> for Error { 16 #[inline(always)] from(_: OutOfBound) -> Self17 fn from(_: OutOfBound) -> Self { 18 ERANGE 19 } 20 } 21 22 /// A helper trait to perform index projection. 23 /// 24 /// This is similar to [`core::slice::SliceIndex`], but operates on raw pointers safely and 25 /// fallibly. 26 /// 27 /// # Safety 28 /// 29 /// The implementation of `index` and `get` (if [`Some`] is returned) must ensure that, if provided 30 /// input pointer `slice` and returned pointer `output`, then: 31 /// - `output` has the same provenance as `slice`; 32 /// - `output.byte_offset_from(slice)` is between 0 to 33 /// `KnownSize::size(slice) - KnownSize::size(output)`. 34 /// 35 /// This means that if the input pointer is valid, then pointer returned by `get` or `index` is 36 /// also valid. 37 #[diagnostic::on_unimplemented(message = "`{Self}` cannot be used to index `{T}`")] 38 #[doc(hidden)] 39 pub unsafe trait ProjectIndex<T: ?Sized>: Sized { 40 type Output: ?Sized; 41 42 /// Returns an index-projected pointer, if in bounds. get(self, slice: *mut T) -> Option<*mut Self::Output>43 fn get(self, slice: *mut T) -> Option<*mut Self::Output>; 44 45 /// Returns an index-projected pointer; fail the build if it cannot be proved to be in bounds. 46 #[inline(always)] index(self, slice: *mut T) -> *mut Self::Output47 fn index(self, slice: *mut T) -> *mut Self::Output { 48 Self::get(self, slice).unwrap_or_else(|| build_error!()) 49 } 50 } 51 52 // Forward array impl to slice impl. 53 // 54 // SAFETY: Safety requirement guaranteed by the forwarded impl. 55 unsafe impl<T, I, const N: usize> ProjectIndex<[T; N]> for I 56 where 57 I: ProjectIndex<[T]>, 58 { 59 type Output = <I as ProjectIndex<[T]>>::Output; 60 61 #[inline(always)] get(self, slice: *mut [T; N]) -> Option<*mut Self::Output>62 fn get(self, slice: *mut [T; N]) -> Option<*mut Self::Output> { 63 <I as ProjectIndex<[T]>>::get(self, slice) 64 } 65 66 #[inline(always)] index(self, slice: *mut [T; N]) -> *mut Self::Output67 fn index(self, slice: *mut [T; N]) -> *mut Self::Output { 68 <I as ProjectIndex<[T]>>::index(self, slice) 69 } 70 } 71 72 // SAFETY: `get`-returned pointer has the same provenance as `slice` and the offset is checked to 73 // not exceed the required bound. 74 unsafe impl<T> ProjectIndex<[T]> for usize { 75 type Output = T; 76 77 #[inline(always)] get(self, slice: *mut [T]) -> Option<*mut T>78 fn get(self, slice: *mut [T]) -> Option<*mut T> { 79 if self >= slice.len() { 80 None 81 } else { 82 Some(slice.cast::<T>().wrapping_add(self)) 83 } 84 } 85 } 86 87 // SAFETY: `get`-returned pointer has the same provenance as `slice` and the offset is checked to 88 // not exceed the required bound. 89 unsafe impl<T> ProjectIndex<[T]> for core::ops::Range<usize> { 90 type Output = [T]; 91 92 #[inline(always)] get(self, slice: *mut [T]) -> Option<*mut [T]>93 fn get(self, slice: *mut [T]) -> Option<*mut [T]> { 94 let new_len = self.end.checked_sub(self.start)?; 95 if self.end > slice.len() { 96 return None; 97 } 98 Some(core::ptr::slice_from_raw_parts_mut( 99 slice.cast::<T>().wrapping_add(self.start), 100 new_len, 101 )) 102 } 103 } 104 105 // SAFETY: Safety requirement guaranteed by the forwarded impl. 106 unsafe impl<T> ProjectIndex<[T]> for core::ops::RangeTo<usize> { 107 type Output = [T]; 108 109 #[inline(always)] get(self, slice: *mut [T]) -> Option<*mut [T]>110 fn get(self, slice: *mut [T]) -> Option<*mut [T]> { 111 (0..self.end).get(slice) 112 } 113 } 114 115 // SAFETY: Safety requirement guaranteed by the forwarded impl. 116 unsafe impl<T> ProjectIndex<[T]> for core::ops::RangeFrom<usize> { 117 type Output = [T]; 118 119 #[inline(always)] get(self, slice: *mut [T]) -> Option<*mut [T]>120 fn get(self, slice: *mut [T]) -> Option<*mut [T]> { 121 (self.start..slice.len()).get(slice) 122 } 123 } 124 125 // SAFETY: `get` returned the pointer as is, so it always has the same provenance and offset of 0. 126 unsafe impl<T> ProjectIndex<[T]> for core::ops::RangeFull { 127 type Output = [T]; 128 129 #[inline(always)] get(self, slice: *mut [T]) -> Option<*mut [T]>130 fn get(self, slice: *mut [T]) -> Option<*mut [T]> { 131 Some(slice) 132 } 133 } 134 135 /// A helper trait to perform field projection. 136 /// 137 /// This trait has a `DEREF` generic parameter so it can be implemented twice for types that 138 /// implement [`Deref`]. This will cause an ambiguity error and thus block [`Deref`] types being 139 /// used as base of projection, as they can inject unsoundness. Users therefore must not specify 140 /// `DEREF` and should always leave it to be inferred. 141 /// 142 /// # Safety 143 /// 144 /// `proj` may only invoke `f` with a valid allocation, as the documentation of [`Self::proj`] 145 /// describes. 146 #[doc(hidden)] 147 pub unsafe trait ProjectField<const DEREF: bool> { 148 /// Project a pointer to a type to a pointer of a field. 149 /// 150 /// `f` may only be invoked with a valid allocation so it can safely obtain raw pointers to 151 /// fields using `&raw mut`. 152 /// 153 /// This is needed because `base` might not point to a valid allocation, while `&raw mut` 154 /// requires pointers to be in bounds of a valid allocation. 155 /// 156 /// # Safety 157 /// 158 /// `f` must return a pointer in bounds of the provided pointer. proj<F>(base: *mut Self, f: impl FnOnce(*mut Self) -> *mut F) -> *mut F159 unsafe fn proj<F>(base: *mut Self, f: impl FnOnce(*mut Self) -> *mut F) -> *mut F; 160 } 161 162 // NOTE: in theory, this API should work for `T: ?Sized` and `F: ?Sized`, too. However, we cannot 163 // currently support that as we need to obtain a valid allocation that `&raw const` can operate on. 164 // 165 // SAFETY: `proj` invokes `f` with valid allocation. 166 unsafe impl<T> ProjectField<false> for T { 167 #[inline(always)] proj<F>(base: *mut Self, f: impl FnOnce(*mut Self) -> *mut F) -> *mut F168 unsafe fn proj<F>(base: *mut Self, f: impl FnOnce(*mut Self) -> *mut F) -> *mut F { 169 // Create a valid allocation to start projection, as `base` is not necessarily so. The 170 // memory is never actually used so it will be optimized out, so it should work even for 171 // very large `T` (`memoffset` crate also relies on this). To be extra certain, we also 172 // annotate `f` closure with `#[inline(always)]` in the macro. 173 let mut place = MaybeUninit::uninit(); 174 let place_base = place.as_mut_ptr(); 175 let field = f(place_base); 176 // SAFETY: `field` is in bounds from `base` per safety requirement. 177 let offset = unsafe { field.byte_offset_from(place_base) }; 178 // Use `wrapping_byte_offset` as `base` does not need to be of valid allocation. 179 base.wrapping_byte_offset(offset).cast() 180 } 181 } 182 183 // SAFETY: Vacuously satisfied. 184 unsafe impl<T: Deref> ProjectField<true> for T { 185 #[inline(always)] proj<F>(_: *mut Self, _: impl FnOnce(*mut Self) -> *mut F) -> *mut F186 unsafe fn proj<F>(_: *mut Self, _: impl FnOnce(*mut Self) -> *mut F) -> *mut F { 187 build_error!("this function is a guard against `Deref` impl and is never invoked"); 188 } 189 } 190 191 /// Create a projection from a raw pointer. 192 /// 193 /// The projected pointer is within the memory region marked by the input pointer. There is no 194 /// requirement that the input raw pointer needs to be valid, so this macro may be used for 195 /// projecting pointers outside normal address space, e.g. I/O pointers. However, if the input 196 /// pointer is valid, the projected pointer is also valid. 197 /// 198 /// Supported projections include field projections and index projections. 199 /// It is not allowed to project into types that implement custom [`Deref`] or 200 /// [`Index`](core::ops::Index). 201 /// 202 /// The macro has basic syntax of `kernel::ptr::project!(ptr, projection)`, where `ptr` is an 203 /// expression that evaluates to a raw pointer which serves as the base of projection. `projection` 204 /// can be a projection expression of form `.field` (normally identifier, or numeral in case of 205 /// tuple structs) or of form `[index]`. 206 /// 207 /// If a mutable pointer is needed, the macro input can be prefixed with the `mut` keyword, i.e. 208 /// `kernel::ptr::project!(mut ptr, projection)`. By default, a const pointer is created. 209 /// 210 /// `ptr::project!` macro can perform both fallible indexing and build-time checked indexing. 211 /// `[index]` form performs build-time bounds checking; if compiler fails to prove `[index]` is in 212 /// bounds, compilation will fail. `[index]?` can be used to perform runtime bounds checking; 213 /// `OutOfBound` error is raised via `?` if the index is out of bounds. 214 /// 215 /// # Examples 216 /// 217 /// Field projections are performed with `.field_name`: 218 /// 219 /// ``` 220 /// struct MyStruct { field: u32, } 221 /// let ptr: *const MyStruct = core::ptr::dangling(); 222 /// let field_ptr: *const u32 = kernel::ptr::project!(ptr, .field); 223 /// 224 /// struct MyTupleStruct(u32, u32); 225 /// 226 /// fn proj(ptr: *const MyTupleStruct) { 227 /// let field_ptr: *const u32 = kernel::ptr::project!(ptr, .1); 228 /// } 229 /// ``` 230 /// 231 /// Index projections are performed with `[index]`: 232 /// 233 /// ``` 234 /// fn proj(ptr: *const [u8; 32]) -> Result { 235 /// let field_ptr: *const u8 = kernel::ptr::project!(ptr, [1]); 236 /// // The following invocation, if uncommented, would fail the build. 237 /// // 238 /// // kernel::ptr::project!(ptr, [128]); 239 /// 240 /// // This will raise an `OutOfBound` error (which is convertible to `ERANGE`). 241 /// kernel::ptr::project!(ptr, [128]?); 242 /// Ok(()) 243 /// } 244 /// ``` 245 /// 246 /// If you need to match on the error instead of propagate, put the invocation inside a closure: 247 /// 248 /// ``` 249 /// let ptr: *const [u8; 32] = core::ptr::dangling(); 250 /// let field_ptr: Result<*const u8> = (|| -> Result<_> { 251 /// Ok(kernel::ptr::project!(ptr, [128]?)) 252 /// })(); 253 /// assert!(field_ptr.is_err()); 254 /// ``` 255 /// 256 /// For mutable pointers, put `mut` as the first token in macro invocation. 257 /// 258 /// ``` 259 /// let ptr: *mut [(u8, u16); 32] = core::ptr::dangling_mut(); 260 /// let field_ptr: *mut u16 = kernel::ptr::project!(mut ptr, [1].1); 261 /// ``` 262 #[macro_export] 263 macro_rules! project_pointer { 264 (@gen $ptr:ident, ) => {}; 265 // Field projection. `$field` needs to be `tt` to support tuple index like `.0`. 266 (@gen $ptr:ident, .$field:tt $($rest:tt)*) => { 267 // SAFETY: The provided closure always returns an in-bounds pointer. 268 let $ptr = unsafe { 269 $crate::ptr::projection::ProjectField::proj($ptr, #[inline(always)] |ptr| { 270 // Check unaligned field. Not all users (e.g. DMA) can handle unaligned 271 // projections. 272 if false { 273 let _ = &(*ptr).$field; 274 } 275 // SAFETY: `$field` is in bounds, and no implicit `Deref` is possible (if the 276 // type implements `Deref`, Rust cannot infer the generic parameter `DEREF`). 277 &raw mut (*ptr).$field 278 }) 279 }; 280 $crate::ptr::project!(@gen $ptr, $($rest)*) 281 }; 282 // Fallible index projection. 283 (@gen $ptr:ident, [$index:expr]? $($rest:tt)*) => { 284 let $ptr = $crate::ptr::projection::ProjectIndex::get($index, $ptr) 285 .ok_or($crate::ptr::projection::OutOfBound)?; 286 $crate::ptr::project!(@gen $ptr, $($rest)*) 287 }; 288 // Build-time checked index projection. 289 (@gen $ptr:ident, [$index:expr] $($rest:tt)*) => { 290 let $ptr = $crate::ptr::projection::ProjectIndex::index($index, $ptr); 291 $crate::ptr::project!(@gen $ptr, $($rest)*) 292 }; 293 (mut $ptr:expr, $($proj:tt)*) => {{ 294 let ptr: *mut _ = $ptr; 295 $crate::ptr::project!(@gen ptr, $($proj)*); 296 ptr 297 }}; 298 ($ptr:expr, $($proj:tt)*) => {{ 299 let ptr = <*const _>::cast_mut($ptr); 300 // We currently always project using mutable pointer, as it is not decided whether `&raw 301 // const` allows the resulting pointer to be mutated (see documentation of `addr_of!`). 302 $crate::ptr::project!(@gen ptr, $($proj)*); 303 ptr.cast_const() 304 }}; 305 } 306