xref: /linux/rust/kernel/transmute.rs (revision 07fdad3a93756b872da7b53647715c48d0f4a2d0)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 //! Traits for transmuting types.
4 
5 use 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.
38 pub 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 a mutable slice of bytes to a reference to `Self`.
62     ///
63     /// Succeeds if the reference is properly aligned, and the size of `bytes` is equal to that of
64     /// `T` and different from zero.
65     ///
66     /// Otherwise, returns [`None`].
67     fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
68     where
69         Self: AsBytes + Sized,
70     {
71         let slice_ptr = bytes.as_mut_ptr().cast::<Self>();
72         let size = size_of::<Self>();
73 
74         #[allow(clippy::incompatible_msrv)]
75         if bytes.len() == size && slice_ptr.is_aligned() {
76             // SAFETY: Size and alignment were just checked.
77             unsafe { Some(&mut *slice_ptr) }
78         } else {
79             None
80         }
81     }
82 
83     /// Creates an owned instance of `Self` by copying `bytes`.
84     ///
85     /// Unlike [`FromBytes::from_bytes`], which requires aligned input, this method can be used on
86     /// non-aligned data at the cost of a copy.
87     fn from_bytes_copy(bytes: &[u8]) -> Option<Self>
88     where
89         Self: Sized,
90     {
91         if bytes.len() == size_of::<Self>() {
92             // SAFETY: we just verified that `bytes` has the same size as `Self`, and per the
93             // invariants of `FromBytes`, any byte sequence of the correct length is a valid value
94             // for `Self`.
95             Some(unsafe { core::ptr::read_unaligned(bytes.as_ptr().cast::<Self>()) })
96         } else {
97             None
98         }
99     }
100 }
101 
102 macro_rules! impl_frombytes {
103     ($($({$($generics:tt)*})? $t:ty, )*) => {
104         // SAFETY: Safety comments written in the macro invocation.
105         $(unsafe impl$($($generics)*)? FromBytes for $t {})*
106     };
107 }
108 
109 impl_frombytes! {
110     // SAFETY: All bit patterns are acceptable values of the types below.
111     u8, u16, u32, u64, usize,
112     i8, i16, i32, i64, isize,
113 
114     // SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
115     // patterns are also acceptable for arrays of that type.
116     {<T: FromBytes>} [T],
117     {<T: FromBytes, const N: usize>} [T; N],
118 }
119 
120 /// Types that can be viewed as an immutable slice of initialized bytes.
121 ///
122 /// If a struct implements this trait, then it is okay to copy it byte-for-byte to userspace. This
123 /// means that it should not have any padding, as padding bytes are uninitialized. Reading
124 /// uninitialized memory is not just undefined behavior, it may even lead to leaking sensitive
125 /// information on the stack to userspace.
126 ///
127 /// The struct should also not hold kernel pointers, as kernel pointer addresses are also considered
128 /// sensitive. However, leaking kernel pointers is not considered undefined behavior by Rust, so
129 /// this is a correctness requirement, but not a safety requirement.
130 ///
131 /// # Safety
132 ///
133 /// Values of this type may not contain any uninitialized bytes. This type must not have interior
134 /// mutability.
135 pub unsafe trait AsBytes {
136     /// Returns `self` as a slice of bytes.
137     fn as_bytes(&self) -> &[u8] {
138         // CAST: `Self` implements `AsBytes` thus all bytes of `self` are initialized.
139         let data = core::ptr::from_ref(self).cast::<u8>();
140         let len = core::mem::size_of_val(self);
141 
142         // SAFETY: `data` is non-null and valid for reads of `len * sizeof::<u8>()` bytes.
143         unsafe { core::slice::from_raw_parts(data, len) }
144     }
145 
146     /// Returns `self` as a mutable slice of bytes.
147     fn as_bytes_mut(&mut self) -> &mut [u8]
148     where
149         Self: FromBytes,
150     {
151         // CAST: `Self` implements both `AsBytes` and `FromBytes` thus making `Self`
152         // bi-directionally transmutable to `[u8; size_of_val(self)]`.
153         let data = core::ptr::from_mut(self).cast::<u8>();
154         let len = core::mem::size_of_val(self);
155 
156         // SAFETY: `data` is non-null and valid for read and writes of `len * sizeof::<u8>()`
157         // bytes.
158         unsafe { core::slice::from_raw_parts_mut(data, len) }
159     }
160 }
161 
162 macro_rules! impl_asbytes {
163     ($($({$($generics:tt)*})? $t:ty, )*) => {
164         // SAFETY: Safety comments written in the macro invocation.
165         $(unsafe impl$($($generics)*)? AsBytes for $t {})*
166     };
167 }
168 
169 impl_asbytes! {
170     // SAFETY: Instances of the following types have no uninitialized portions.
171     u8, u16, u32, u64, usize,
172     i8, i16, i32, i64, isize,
173     bool,
174     char,
175     str,
176 
177     // SAFETY: If individual values in an array have no uninitialized portions, then the array
178     // itself does not have any uninitialized portions either.
179     {<T: AsBytes>} [T],
180     {<T: AsBytes, const N: usize>} [T; N],
181 }
182