Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit ce1c54f

Browse files
plinkrojeda
authored andcommittedOct 9, 2024
rust: kernel: move FromBytes and AsBytes traits to a new transmute module
Refactor the `FromBytes` and `AsBytes` traits from `types.rs` into a new `transmute.rs` module: - Add `rust/kernel/transmute.rs` with the definitions of `FromBytes` and `AsBytes`. - Remove the same trait definitions from `rust/kernel/types.rs`. - Update `rust/kernel/uaccess.rs` to import `AsBytes` and `FromBytes` from `transmute.rs`. The traits and their implementations remain unchanged. Suggested-by: Benno Lossin <benno.lossin@proton.me> Link: #1117 Signed-off-by: Aliet Exposito Garcia <aliet.exposito@gmail.com> Reviewed-by: Fiona Behrens <me@kloenk.dev> Reviewed-by: Benno Lossin <benno.lossin@proton.me> Link: https://lore.kernel.org/r/20240918225115.2309224-2-aliet.exposito@gmail.com [ Rebased on top of the lints series and slightly reworded. - Miguel ] Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
1 parent e9759c5 commit ce1c54f

File tree

4 files changed

+73
-69
lines changed

4 files changed

+73
-69
lines changed
 

‎rust/kernel/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub mod str;
5454
pub mod sync;
5555
pub mod task;
5656
pub mod time;
57+
pub mod transmute;
5758
pub mod types;
5859
pub mod uaccess;
5960
pub mod workqueue;

‎rust/kernel/transmute.rs

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
//! Traits for transmuting types.
4+
5+
/// Types for which any bit pattern is valid.
6+
///
7+
/// Not all types are valid for all values. For example, a `bool` must be either zero or one, so
8+
/// reading arbitrary bytes into something that contains a `bool` is not okay.
9+
///
10+
/// It's okay for the type to have padding, as initializing those bytes has no effect.
11+
///
12+
/// # Safety
13+
///
14+
/// All bit-patterns must be valid for this type. This type must not have interior mutability.
15+
pub unsafe trait FromBytes {}
16+
17+
macro_rules! impl_frombytes {
18+
($($({$($generics:tt)*})? $t:ty, )*) => {
19+
// SAFETY: Safety comments written in the macro invocation.
20+
$(unsafe impl$($($generics)*)? FromBytes for $t {})*
21+
};
22+
}
23+
24+
impl_frombytes! {
25+
// SAFETY: All bit patterns are acceptable values of the types below.
26+
u8, u16, u32, u64, usize,
27+
i8, i16, i32, i64, isize,
28+
29+
// SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
30+
// patterns are also acceptable for arrays of that type.
31+
{<T: FromBytes>} [T],
32+
{<T: FromBytes, const N: usize>} [T; N],
33+
}
34+
35+
/// Types that can be viewed as an immutable slice of initialized bytes.
36+
///
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.
41+
///
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.
45+
///
46+
/// # Safety
47+
///
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,
66+
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],
71+
}

‎rust/kernel/types.rs

-68
Original file line numberDiff line numberDiff line change
@@ -479,71 +479,3 @@ pub enum Either<L, R> {
479479
/// Constructs an instance of [`Either`] containing a value of type `R`.
480480
Right(R),
481481
}
482-
483-
/// Types for which any bit pattern is valid.
484-
///
485-
/// Not all types are valid for all values. For example, a `bool` must be either zero or one, so
486-
/// reading arbitrary bytes into something that contains a `bool` is not okay.
487-
///
488-
/// It's okay for the type to have padding, as initializing those bytes has no effect.
489-
///
490-
/// # Safety
491-
///
492-
/// All bit-patterns must be valid for this type. This type must not have interior mutability.
493-
pub unsafe trait FromBytes {}
494-
495-
macro_rules! impl_frombytes {
496-
($($({$($generics:tt)*})? $t:ty, )*) => {
497-
// SAFETY: Safety comments written in the macro invocation.
498-
$(unsafe impl$($($generics)*)? FromBytes for $t {})*
499-
};
500-
}
501-
502-
impl_frombytes! {
503-
// SAFETY: All bit patterns are acceptable values of the types below.
504-
u8, u16, u32, u64, usize,
505-
i8, i16, i32, i64, isize,
506-
507-
// SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
508-
// patterns are also acceptable for arrays of that type.
509-
{<T: FromBytes>} [T],
510-
{<T: FromBytes, const N: usize>} [T; N],
511-
}
512-
513-
/// Types that can be viewed as an immutable slice of initialized bytes.
514-
///
515-
/// If a struct implements this trait, then it is okay to copy it byte-for-byte to userspace. This
516-
/// means that it should not have any padding, as padding bytes are uninitialized. Reading
517-
/// uninitialized memory is not just undefined behavior, it may even lead to leaking sensitive
518-
/// information on the stack to userspace.
519-
///
520-
/// The struct should also not hold kernel pointers, as kernel pointer addresses are also considered
521-
/// sensitive. However, leaking kernel pointers is not considered undefined behavior by Rust, so
522-
/// this is a correctness requirement, but not a safety requirement.
523-
///
524-
/// # Safety
525-
///
526-
/// Values of this type may not contain any uninitialized bytes. This type must not have interior
527-
/// mutability.
528-
pub unsafe trait AsBytes {}
529-
530-
macro_rules! impl_asbytes {
531-
($($({$($generics:tt)*})? $t:ty, )*) => {
532-
// SAFETY: Safety comments written in the macro invocation.
533-
$(unsafe impl$($($generics)*)? AsBytes for $t {})*
534-
};
535-
}
536-
537-
impl_asbytes! {
538-
// SAFETY: Instances of the following types have no uninitialized portions.
539-
u8, u16, u32, u64, usize,
540-
i8, i16, i32, i64, isize,
541-
bool,
542-
char,
543-
str,
544-
545-
// SAFETY: If individual values in an array have no uninitialized portions, then the array
546-
// itself does not have any uninitialized portions either.
547-
{<T: AsBytes>} [T],
548-
{<T: AsBytes, const N: usize>} [T; N],
549-
}

‎rust/kernel/uaccess.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use crate::{
99
bindings,
1010
error::Result,
1111
prelude::*,
12-
types::{AsBytes, FromBytes},
12+
transmute::{AsBytes, FromBytes},
1313
};
1414
use alloc::vec::Vec;
1515
use core::ffi::{c_ulong, c_void};

0 commit comments

Comments
 (0)
Failed to load comments.