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