Skip to main content

kernel/
transmute.rs

1// SPDX-License-Identifier: GPL-2.0
2
3//! Traits for transmuting types.
4
5use core::mem::size_of;
6
7/// Types for which any bit pattern is valid.
8///
9/// Not all types are valid for all values. For example, a `bool` must be either zero or one, so
10/// reading arbitrary bytes into something that contains a `bool` is not okay.
11///
12/// It's okay for the type to have padding, as initializing those bytes has no effect.
13///
14/// # Examples
15///
16/// ```
17/// use kernel::transmute::FromBytes;
18///
19/// # fn test() -> Option<()> {
20/// let raw = [1, 2, 3, 4];
21///
22/// let result = u32::from_bytes(&raw)?;
23///
24/// #[cfg(target_endian = "little")]
25/// assert_eq!(*result, 0x4030201);
26///
27/// #[cfg(target_endian = "big")]
28/// assert_eq!(*result, 0x1020304);
29///
30/// # Some(()) }
31/// # test().ok_or(EINVAL)?;
32/// # Ok::<(), Error>(())
33/// ```
34///
35/// # Safety
36///
37/// All bit-patterns must be valid for this type. This type must not have interior mutability.
38pub unsafe trait FromBytes {
39    /// Converts a slice of bytes to a reference to `Self`.
40    ///
41    /// Succeeds if the reference is properly aligned, and the size of `bytes` is equal to that of
42    /// `T` and different from zero.
43    ///
44    /// Otherwise, returns [`None`].
45    fn from_bytes(bytes: &[u8]) -> Option<&Self>
46    where
47        Self: Sized,
48    {
49        let slice_ptr = bytes.as_ptr().cast::<Self>();
50        let size = size_of::<Self>();
51
52        if bytes.len() == size && slice_ptr.is_aligned() {
53            // SAFETY: Size and alignment were just checked.
54            unsafe { Some(&*slice_ptr) }
55        } else {
56            None
57        }
58    }
59
60    /// Converts the beginning of `bytes` to a reference to `Self`.
61    ///
62    /// This method is similar to [`Self::from_bytes`], with the difference that `bytes` does not
63    /// need to be the same size of `Self` - the appropriate portion is cut from the beginning of
64    /// `bytes`, and the remainder returned alongside `Self`.
65    fn from_bytes_prefix(bytes: &[u8]) -> Option<(&Self, &[u8])>
66    where
67        Self: Sized,
68    {
69        let (prefix, remainder) = bytes.split_at_checked(size_of::<Self>())?;
70
71        Self::from_bytes(prefix).map(|s| (s, remainder))
72    }
73
74    /// Converts a mutable slice of bytes to a reference to `Self`.
75    ///
76    /// Succeeds if the reference is properly aligned, and the size of `bytes` is equal to that of
77    /// `T` and different from zero.
78    ///
79    /// Otherwise, returns [`None`].
80    fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
81    where
82        Self: AsBytes + Sized,
83    {
84        let slice_ptr = bytes.as_mut_ptr().cast::<Self>();
85        let size = size_of::<Self>();
86
87        if bytes.len() == size && slice_ptr.is_aligned() {
88            // SAFETY: Size and alignment were just checked.
89            unsafe { Some(&mut *slice_ptr) }
90        } else {
91            None
92        }
93    }
94
95    /// Converts the beginning of `bytes` to a mutable reference to `Self`.
96    ///
97    /// This method is similar to [`Self::from_bytes_mut`], with the difference that `bytes` does
98    /// not need to be the same size of `Self` - the appropriate portion is cut from the beginning
99    /// of `bytes`, and the remainder returned alongside `Self`.
100    fn from_bytes_mut_prefix(bytes: &mut [u8]) -> Option<(&mut Self, &mut [u8])>
101    where
102        Self: AsBytes + Sized,
103    {
104        let (prefix, remainder) = bytes.split_at_mut_checked(size_of::<Self>())?;
105
106        Self::from_bytes_mut(prefix).map(|s| (s, remainder))
107    }
108
109    /// Creates an owned instance of `Self` by copying `bytes`.
110    ///
111    /// Unlike [`FromBytes::from_bytes`], which requires aligned input, this method can be used on
112    /// non-aligned data at the cost of a copy.
113    fn from_bytes_copy(bytes: &[u8]) -> Option<Self>
114    where
115        Self: Sized,
116    {
117        if bytes.len() == size_of::<Self>() {
118            // SAFETY: we just verified that `bytes` has the same size as `Self`, and per the
119            // invariants of `FromBytes`, any byte sequence of the correct length is a valid value
120            // for `Self`.
121            Some(unsafe { core::ptr::read_unaligned(bytes.as_ptr().cast::<Self>()) })
122        } else {
123            None
124        }
125    }
126
127    /// Creates an owned instance of `Self` from the beginning of `bytes`.
128    ///
129    /// This method is similar to [`Self::from_bytes_copy`], with the difference that `bytes` does
130    /// not need to be the same size of `Self` - the appropriate portion is cut from the beginning
131    /// of `bytes`, and the remainder returned alongside `Self`.
132    fn from_bytes_copy_prefix(bytes: &[u8]) -> Option<(Self, &[u8])>
133    where
134        Self: Sized,
135    {
136        let (prefix, remainder) = bytes.split_at_checked(size_of::<Self>())?;
137
138        Self::from_bytes_copy(prefix).map(|s| (s, remainder))
139    }
140}
141
142macro_rules! impl_frombytes {
143    ($($({$($generics:tt)*})? $t:ty, )*) => {
144        // SAFETY: Safety comments written in the macro invocation.
145        $(unsafe impl$($($generics)*)? FromBytes for $t {})*
146    };
147}
148
149impl_frombytes! {
150    // SAFETY: Inhabited ZSTs only have one possible bit pattern, and these two have no invariant.
151    (),
152    {<T>} core::marker::PhantomData<T>,
153
154    // SAFETY: All bit patterns are acceptable values of the types below.
155    u8, u16, u32, u64, usize,
156    i8, i16, i32, i64, isize,
157
158    // SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
159    // patterns are also acceptable for arrays of that type.
160    {<T: FromBytes>} [T],
161    {<T: FromBytes, const N: usize>} [T; N],
162}
163
164/// Types that can be viewed as an immutable slice of initialized bytes.
165///
166/// If a struct implements this trait, then it is okay to copy it byte-for-byte to userspace. This
167/// means that it should not have any padding, as padding bytes are uninitialized. Reading
168/// uninitialized memory is not just undefined behavior, it may even lead to leaking sensitive
169/// information on the stack to userspace.
170///
171/// The struct should also not hold kernel pointers, as kernel pointer addresses are also considered
172/// sensitive. However, leaking kernel pointers is not considered undefined behavior by Rust, so
173/// this is a correctness requirement, but not a safety requirement.
174///
175/// # Safety
176///
177/// Values of this type may not contain any uninitialized bytes. This type must not have interior
178/// mutability.
179pub unsafe trait AsBytes {
180    /// Returns `self` as a slice of bytes.
181    fn as_bytes(&self) -> &[u8] {
182        // CAST: `Self` implements `AsBytes` thus all bytes of `self` are initialized.
183        let data = core::ptr::from_ref(self).cast::<u8>();
184        let len = core::mem::size_of_val(self);
185
186        // SAFETY: `data` is non-null and valid for reads of `len * sizeof::<u8>()` bytes.
187        unsafe { core::slice::from_raw_parts(data, len) }
188    }
189
190    /// Returns `self` as a mutable slice of bytes.
191    fn as_bytes_mut(&mut self) -> &mut [u8]
192    where
193        Self: FromBytes,
194    {
195        // CAST: `Self` implements both `AsBytes` and `FromBytes` thus making `Self`
196        // bi-directionally transmutable to `[u8; size_of_val(self)]`.
197        let data = core::ptr::from_mut(self).cast::<u8>();
198        let len = core::mem::size_of_val(self);
199
200        // SAFETY: `data` is non-null and valid for read and writes of `len * sizeof::<u8>()`
201        // bytes.
202        unsafe { core::slice::from_raw_parts_mut(data, len) }
203    }
204}
205
206macro_rules! impl_asbytes {
207    ($($({$($generics:tt)*})? $t:ty, )*) => {
208        // SAFETY: Safety comments written in the macro invocation.
209        $(unsafe impl$($($generics)*)? AsBytes for $t {})*
210    };
211}
212
213impl_asbytes! {
214    // SAFETY: Inhabited ZSTs only have one possible bit pattern, and these two have no invariant.
215    (),
216    {<T>} core::marker::PhantomData<T>,
217
218    // SAFETY: Instances of the following types have no uninitialized portions.
219    u8, u16, u32, u64, usize,
220    i8, i16, i32, i64, isize,
221    bool,
222    char,
223    str,
224
225    // SAFETY: If individual values in an array have no uninitialized portions, then the array
226    // itself does not have any uninitialized portions either.
227    {<T: AsBytes>} [T],
228    {<T: AsBytes, const N: usize>} [T; N],
229}