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 #[allow(clippy::incompatible_msrv)]
53 if bytes.len() == size && slice_ptr.is_aligned() {
54 // SAFETY: Size and alignment were just checked.
55 unsafe { Some(&*slice_ptr) }
56 } else {
57 None
58 }
59 }
60
61 /// Converts the beginning of `bytes` to a reference to `Self`.
62 ///
63 /// This method is similar to [`Self::from_bytes`], with the difference that `bytes` does not
64 /// need to be the same size of `Self` - the appropriate portion is cut from the beginning of
65 /// `bytes`, and the remainder returned alongside `Self`.
66 fn from_bytes_prefix(bytes: &[u8]) -> Option<(&Self, &[u8])>
67 where
68 Self: Sized,
69 {
70 if bytes.len() < size_of::<Self>() {
71 None
72 } else {
73 // PANIC: We checked that `bytes.len() >= size_of::<Self>`, thus `split_at` cannot
74 // panic.
75 // TODO: replace with `split_at_checked` once the MSRV is >= 1.80.
76 let (prefix, remainder) = bytes.split_at(size_of::<Self>());
77
78 Self::from_bytes(prefix).map(|s| (s, remainder))
79 }
80 }
81
82 /// Converts a mutable slice of bytes to a reference to `Self`.
83 ///
84 /// Succeeds if the reference is properly aligned, and the size of `bytes` is equal to that of
85 /// `T` and different from zero.
86 ///
87 /// Otherwise, returns [`None`].
88 fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
89 where
90 Self: AsBytes + Sized,
91 {
92 let slice_ptr = bytes.as_mut_ptr().cast::<Self>();
93 let size = size_of::<Self>();
94
95 #[allow(clippy::incompatible_msrv)]
96 if bytes.len() == size && slice_ptr.is_aligned() {
97 // SAFETY: Size and alignment were just checked.
98 unsafe { Some(&mut *slice_ptr) }
99 } else {
100 None
101 }
102 }
103
104 /// Converts the beginning of `bytes` to a mutable reference to `Self`.
105 ///
106 /// This method is similar to [`Self::from_bytes_mut`], with the difference that `bytes` does
107 /// not need to be the same size of `Self` - the appropriate portion is cut from the beginning
108 /// of `bytes`, and the remainder returned alongside `Self`.
109 fn from_bytes_mut_prefix(bytes: &mut [u8]) -> Option<(&mut Self, &mut [u8])>
110 where
111 Self: AsBytes + Sized,
112 {
113 if bytes.len() < size_of::<Self>() {
114 None
115 } else {
116 // PANIC: We checked that `bytes.len() >= size_of::<Self>`, thus `split_at_mut` cannot
117 // panic.
118 // TODO: replace with `split_at_mut_checked` once the MSRV is >= 1.80.
119 let (prefix, remainder) = bytes.split_at_mut(size_of::<Self>());
120
121 Self::from_bytes_mut(prefix).map(|s| (s, remainder))
122 }
123 }
124
125 /// Creates an owned instance of `Self` by copying `bytes`.
126 ///
127 /// Unlike [`FromBytes::from_bytes`], which requires aligned input, this method can be used on
128 /// non-aligned data at the cost of a copy.
129 fn from_bytes_copy(bytes: &[u8]) -> Option<Self>
130 where
131 Self: Sized,
132 {
133 if bytes.len() == size_of::<Self>() {
134 // SAFETY: we just verified that `bytes` has the same size as `Self`, and per the
135 // invariants of `FromBytes`, any byte sequence of the correct length is a valid value
136 // for `Self`.
137 Some(unsafe { core::ptr::read_unaligned(bytes.as_ptr().cast::<Self>()) })
138 } else {
139 None
140 }
141 }
142
143 /// Creates an owned instance of `Self` from the beginning of `bytes`.
144 ///
145 /// This method is similar to [`Self::from_bytes_copy`], with the difference that `bytes` does
146 /// not need to be the same size of `Self` - the appropriate portion is cut from the beginning
147 /// of `bytes`, and the remainder returned alongside `Self`.
148 fn from_bytes_copy_prefix(bytes: &[u8]) -> Option<(Self, &[u8])>
149 where
150 Self: Sized,
151 {
152 if bytes.len() < size_of::<Self>() {
153 None
154 } else {
155 // PANIC: We checked that `bytes.len() >= size_of::<Self>`, thus `split_at` cannot
156 // panic.
157 // TODO: replace with `split_at_checked` once the MSRV is >= 1.80.
158 let (prefix, remainder) = bytes.split_at(size_of::<Self>());
159
160 Self::from_bytes_copy(prefix).map(|s| (s, remainder))
161 }
162 }
163}
164
165macro_rules! impl_frombytes {
166 ($($({$($generics:tt)*})? $t:ty, )*) => {
167 // SAFETY: Safety comments written in the macro invocation.
168 $(unsafe impl$($($generics)*)? FromBytes for $t {})*
169 };
170}
171
172impl_frombytes! {
173 // SAFETY: All bit patterns are acceptable values of the types below.
174 u8, u16, u32, u64, usize,
175 i8, i16, i32, i64, isize,
176
177 // SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
178 // patterns are also acceptable for arrays of that type.
179 {<T: FromBytes>} [T],
180 {<T: FromBytes, const N: usize>} [T; N],
181}
182
183/// Types that can be viewed as an immutable slice of initialized bytes.
184///
185/// If a struct implements this trait, then it is okay to copy it byte-for-byte to userspace. This
186/// means that it should not have any padding, as padding bytes are uninitialized. Reading
187/// uninitialized memory is not just undefined behavior, it may even lead to leaking sensitive
188/// information on the stack to userspace.
189///
190/// The struct should also not hold kernel pointers, as kernel pointer addresses are also considered
191/// sensitive. However, leaking kernel pointers is not considered undefined behavior by Rust, so
192/// this is a correctness requirement, but not a safety requirement.
193///
194/// # Safety
195///
196/// Values of this type may not contain any uninitialized bytes. This type must not have interior
197/// mutability.
198pub unsafe trait AsBytes {
199 /// Returns `self` as a slice of bytes.
200 fn as_bytes(&self) -> &[u8] {
201 // CAST: `Self` implements `AsBytes` thus all bytes of `self` are initialized.
202 let data = core::ptr::from_ref(self).cast::<u8>();
203 let len = core::mem::size_of_val(self);
204
205 // SAFETY: `data` is non-null and valid for reads of `len * sizeof::<u8>()` bytes.
206 unsafe { core::slice::from_raw_parts(data, len) }
207 }
208
209 /// Returns `self` as a mutable slice of bytes.
210 fn as_bytes_mut(&mut self) -> &mut [u8]
211 where
212 Self: FromBytes,
213 {
214 // CAST: `Self` implements both `AsBytes` and `FromBytes` thus making `Self`
215 // bi-directionally transmutable to `[u8; size_of_val(self)]`.
216 let data = core::ptr::from_mut(self).cast::<u8>();
217 let len = core::mem::size_of_val(self);
218
219 // SAFETY: `data` is non-null and valid for read and writes of `len * sizeof::<u8>()`
220 // bytes.
221 unsafe { core::slice::from_raw_parts_mut(data, len) }
222 }
223}
224
225macro_rules! impl_asbytes {
226 ($($({$($generics:tt)*})? $t:ty, )*) => {
227 // SAFETY: Safety comments written in the macro invocation.
228 $(unsafe impl$($($generics)*)? AsBytes for $t {})*
229 };
230}
231
232impl_asbytes! {
233 // SAFETY: Instances of the following types have no uninitialized portions.
234 u8, u16, u32, u64, usize,
235 i8, i16, i32, i64, isize,
236 bool,
237 char,
238 str,
239
240 // SAFETY: If individual values in an array have no uninitialized portions, then the array
241 // itself does not have any uninitialized portions either.
242 {<T: AsBytes>} [T],
243 {<T: AsBytes, const N: usize>} [T; N],
244}