xref: /linux/rust/kernel/transmute.rs (revision c771600c6af14749609b49565ffb4cac2959710d)
1*ce1c54fdSAliet Exposito Garcia // SPDX-License-Identifier: GPL-2.0
2*ce1c54fdSAliet Exposito Garcia 
3*ce1c54fdSAliet Exposito Garcia //! Traits for transmuting types.
4*ce1c54fdSAliet Exposito Garcia 
5*ce1c54fdSAliet Exposito Garcia /// Types for which any bit pattern is valid.
6*ce1c54fdSAliet Exposito Garcia ///
7*ce1c54fdSAliet Exposito Garcia /// Not all types are valid for all values. For example, a `bool` must be either zero or one, so
8*ce1c54fdSAliet Exposito Garcia /// reading arbitrary bytes into something that contains a `bool` is not okay.
9*ce1c54fdSAliet Exposito Garcia ///
10*ce1c54fdSAliet Exposito Garcia /// It's okay for the type to have padding, as initializing those bytes has no effect.
11*ce1c54fdSAliet Exposito Garcia ///
12*ce1c54fdSAliet Exposito Garcia /// # Safety
13*ce1c54fdSAliet Exposito Garcia ///
14*ce1c54fdSAliet Exposito Garcia /// All bit-patterns must be valid for this type. This type must not have interior mutability.
15*ce1c54fdSAliet Exposito Garcia pub unsafe trait FromBytes {}
16*ce1c54fdSAliet Exposito Garcia 
17*ce1c54fdSAliet Exposito Garcia macro_rules! impl_frombytes {
18*ce1c54fdSAliet Exposito Garcia     ($($({$($generics:tt)*})? $t:ty, )*) => {
19*ce1c54fdSAliet Exposito Garcia         // SAFETY: Safety comments written in the macro invocation.
20*ce1c54fdSAliet Exposito Garcia         $(unsafe impl$($($generics)*)? FromBytes for $t {})*
21*ce1c54fdSAliet Exposito Garcia     };
22*ce1c54fdSAliet Exposito Garcia }
23*ce1c54fdSAliet Exposito Garcia 
24*ce1c54fdSAliet Exposito Garcia impl_frombytes! {
25*ce1c54fdSAliet Exposito Garcia     // SAFETY: All bit patterns are acceptable values of the types below.
26*ce1c54fdSAliet Exposito Garcia     u8, u16, u32, u64, usize,
27*ce1c54fdSAliet Exposito Garcia     i8, i16, i32, i64, isize,
28*ce1c54fdSAliet Exposito Garcia 
29*ce1c54fdSAliet Exposito Garcia     // SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
30*ce1c54fdSAliet Exposito Garcia     // patterns are also acceptable for arrays of that type.
31*ce1c54fdSAliet Exposito Garcia     {<T: FromBytes>} [T],
32*ce1c54fdSAliet Exposito Garcia     {<T: FromBytes, const N: usize>} [T; N],
33*ce1c54fdSAliet Exposito Garcia }
34*ce1c54fdSAliet Exposito Garcia 
35*ce1c54fdSAliet Exposito Garcia /// Types that can be viewed as an immutable slice of initialized bytes.
36*ce1c54fdSAliet Exposito Garcia ///
37*ce1c54fdSAliet Exposito Garcia /// If a struct implements this trait, then it is okay to copy it byte-for-byte to userspace. This
38*ce1c54fdSAliet Exposito Garcia /// means that it should not have any padding, as padding bytes are uninitialized. Reading
39*ce1c54fdSAliet Exposito Garcia /// uninitialized memory is not just undefined behavior, it may even lead to leaking sensitive
40*ce1c54fdSAliet Exposito Garcia /// information on the stack to userspace.
41*ce1c54fdSAliet Exposito Garcia ///
42*ce1c54fdSAliet Exposito Garcia /// The struct should also not hold kernel pointers, as kernel pointer addresses are also considered
43*ce1c54fdSAliet Exposito Garcia /// sensitive. However, leaking kernel pointers is not considered undefined behavior by Rust, so
44*ce1c54fdSAliet Exposito Garcia /// this is a correctness requirement, but not a safety requirement.
45*ce1c54fdSAliet Exposito Garcia ///
46*ce1c54fdSAliet Exposito Garcia /// # Safety
47*ce1c54fdSAliet Exposito Garcia ///
48*ce1c54fdSAliet Exposito Garcia /// Values of this type may not contain any uninitialized bytes. This type must not have interior
49*ce1c54fdSAliet Exposito Garcia /// mutability.
50*ce1c54fdSAliet Exposito Garcia pub unsafe trait AsBytes {}
51*ce1c54fdSAliet Exposito Garcia 
52*ce1c54fdSAliet Exposito Garcia macro_rules! impl_asbytes {
53*ce1c54fdSAliet Exposito Garcia     ($($({$($generics:tt)*})? $t:ty, )*) => {
54*ce1c54fdSAliet Exposito Garcia         // SAFETY: Safety comments written in the macro invocation.
55*ce1c54fdSAliet Exposito Garcia         $(unsafe impl$($($generics)*)? AsBytes for $t {})*
56*ce1c54fdSAliet Exposito Garcia     };
57*ce1c54fdSAliet Exposito Garcia }
58*ce1c54fdSAliet Exposito Garcia 
59*ce1c54fdSAliet Exposito Garcia impl_asbytes! {
60*ce1c54fdSAliet Exposito Garcia     // SAFETY: Instances of the following types have no uninitialized portions.
61*ce1c54fdSAliet Exposito Garcia     u8, u16, u32, u64, usize,
62*ce1c54fdSAliet Exposito Garcia     i8, i16, i32, i64, isize,
63*ce1c54fdSAliet Exposito Garcia     bool,
64*ce1c54fdSAliet Exposito Garcia     char,
65*ce1c54fdSAliet Exposito Garcia     str,
66*ce1c54fdSAliet Exposito Garcia 
67*ce1c54fdSAliet Exposito Garcia     // SAFETY: If individual values in an array have no uninitialized portions, then the array
68*ce1c54fdSAliet Exposito Garcia     // itself does not have any uninitialized portions either.
69*ce1c54fdSAliet Exposito Garcia     {<T: AsBytes>} [T],
70*ce1c54fdSAliet Exposito Garcia     {<T: AsBytes, const N: usize>} [T; N],
71*ce1c54fdSAliet Exposito Garcia }
72