Skip to content

Commit 052dca5

Browse files
Every2intel-lab-lkp
authored andcommitted
rust: transmute: Add implementation for FromBytes trait
Add implementation and documentation for FromBytes trait. Add new feature block in order to allow using ToBytes and bound to from_bytes_mut function. I'm adding this feature because is possible create a value with disallowed bit pattern and as_byte_mut could create such value by mutating the array and acessing the original value. So adding ToBytes this can be avoided. Link: Rust-for-Linux#1119 Signed-off-by: Christian dos Santos de Lima <[email protected]>
1 parent ce1c54f commit 052dca5

File tree

2 files changed

+88
-34
lines changed

2 files changed

+88
-34
lines changed

rust/kernel/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#![feature(lint_reasons)]
1919
#![feature(new_uninit)]
2020
#![feature(unsize)]
21+
#![feature(portable_simd)]
22+
#![feature(trivial_bounds)]
2123

2224
// Ensure conditional compilation based on the kernel configuration works;
2325
// otherwise we may silently break things like initcall handling.

rust/kernel/transmute.rs

+86-34
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,66 @@
22

33
//! Traits for transmuting types.
44
5+
use core::simd::ToBytes;
56
/// Types for which any bit pattern is valid.
67
///
78
/// Not all types are valid for all values. For example, a `bool` must be either zero or one, so
89
/// reading arbitrary bytes into something that contains a `bool` is not okay.
910
///
1011
/// It's okay for the type to have padding, as initializing those bytes has no effect.
1112
///
13+
/// # Example
14+
///
15+
/// This example is how to use the FromBytes trait
16+
/// ```
17+
/// // Initialize a slice of bytes
18+
/// let foo = &[1, 2, 3, 4];
19+
///
20+
/// //Use the function implemented by trait in integer type
21+
/// let result = u8::from_bytes(foo);
22+
///
23+
/// assert_eq!(*result, 0x4030201);
24+
/// ```
1225
/// # Safety
1326
///
1427
/// All bit-patterns must be valid for this type. This type must not have interior mutability.
15-
pub unsafe trait FromBytes {}
28+
pub unsafe trait FromBytes {
29+
///Get an imutable slice of bytes and converts to a reference to Self
30+
unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self;
31+
/// Get a mutable slice of bytes and converts to a reference to Self
32+
///
33+
/// # Safety
34+
///
35+
/// Bound ToBytes in order to avoid use with disallowed bit patterns
36+
unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
37+
where
38+
Self: ToBytes;
39+
}
1640

41+
//Get a reference of slice of bytes and converts into a reference of integer or a slice with a defined size
1742
macro_rules! impl_frombytes {
1843
($($({$($generics:tt)*})? $t:ty, )*) => {
1944
// SAFETY: Safety comments written in the macro invocation.
20-
$(unsafe impl$($($generics)*)? FromBytes for $t {})*
45+
$(unsafe impl$($($generics)*)? FromBytes for $t {
46+
unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self
47+
{
48+
unsafe {
49+
let slice_ptr = slice_of_bytes.as_ptr() as *const Self;
50+
&*slice_ptr
51+
}
52+
}
53+
54+
unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
55+
where
56+
Self: ToBytes,
57+
{
58+
unsafe {
59+
let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut Self;
60+
&mut *slice_ptr
61+
}
62+
63+
}
64+
})*
2165
};
2266
}
2367

@@ -28,44 +72,52 @@ impl_frombytes! {
2872

2973
// SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
3074
// patterns are also acceptable for arrays of that type.
31-
{<T: FromBytes>} [T],
3275
{<T: FromBytes, const N: usize>} [T; N],
3376
}
3477

35-
/// Types that can be viewed as an immutable slice of initialized bytes.
78+
/// Get a reference of slice of bytes and converts into a reference of an array of integers
3679
///
37-
/// If a struct implements this trait, then it is okay to copy it byte-for-byte to userspace. This
38-
/// means that it should not have any padding, as padding bytes are uninitialized. Reading
39-
/// uninitialized memory is not just undefined behavior, it may even lead to leaking sensitive
40-
/// information on the stack to userspace.
80+
/// Types for which any bit pattern is valid.
4181
///
42-
/// The struct should also not hold kernel pointers, as kernel pointer addresses are also considered
43-
/// sensitive. However, leaking kernel pointers is not considered undefined behavior by Rust, so
44-
/// this is a correctness requirement, but not a safety requirement.
82+
/// Not all types are valid for all values. For example, a `bool` must be either zero or one, so
83+
/// reading arbitrary bytes into something that contains a `bool` is not okay.
4584
///
46-
/// # Safety
85+
/// It's okay for the type to have padding, as initializing those bytes has no effect.
4786
///
48-
/// Values of this type may not contain any uninitialized bytes. This type must not have interior
49-
/// mutability.
50-
pub unsafe trait AsBytes {}
51-
52-
macro_rules! impl_asbytes {
53-
($($({$($generics:tt)*})? $t:ty, )*) => {
54-
// SAFETY: Safety comments written in the macro invocation.
55-
$(unsafe impl$($($generics)*)? AsBytes for $t {})*
56-
};
57-
}
58-
59-
impl_asbytes! {
60-
// SAFETY: Instances of the following types have no uninitialized portions.
61-
u8, u16, u32, u64, usize,
62-
i8, i16, i32, i64, isize,
63-
bool,
64-
char,
65-
str,
87+
/// # Example
88+
///
89+
/// This example is how to use the FromBytes trait
90+
/// ```
91+
/// // Initialize a slice of bytes
92+
/// let foo = &[1, 2, 3, 4];
93+
///
94+
/// //Use the function implemented by trait in integer type
95+
/// let result = <[u32]>::from_bytes(slice_of_bytes);
96+
///
97+
/// assert_eq!(*result, 0x4030201);
98+
/// ```
99+
// SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
100+
// patterns are also acceptable for arrays of that type.
101+
unsafe impl<T: FromBytes> FromBytes for [T] {
102+
unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
103+
//Safety: Guarantee that all values are initiliazed
104+
unsafe {
105+
let slice_ptr = slice_of_bytes.as_ptr() as *const T;
106+
let slice_len = slice_of_bytes.len() / core::mem::size_of::<T>();
107+
core::slice::from_raw_parts(slice_ptr, slice_len)
108+
}
109+
}
66110

67-
// SAFETY: If individual values in an array have no uninitialized portions, then the array
68-
// itself does not have any uninitialized portions either.
69-
{<T: AsBytes>} [T],
70-
{<T: AsBytes, const N: usize>} [T; N],
111+
//Safety: Guarantee that all values are initiliazed
112+
unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
113+
where
114+
Self: ToBytes,
115+
{
116+
//Safety: Guarantee that all values are initiliazed
117+
unsafe {
118+
let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut T;
119+
let slice_len = slice_of_bytes.len() / core::mem::size_of::<T>();
120+
core::slice::from_raw_parts_mut(slice_ptr, slice_len)
121+
}
122+
}
71123
}

0 commit comments

Comments
 (0)