* [PATCH v6] rust: transmute: Add methods for FromBytes trait
@ 2025-03-30 23:40 Christian S. Lima
2025-03-30 23:40 ` [PATCH] " Christian S. Lima
` (3 more replies)
0 siblings, 4 replies; 11+ messages in thread
From: Christian S. Lima @ 2025-03-30 23:40 UTC (permalink / raw)
To: rust-for-linux, linux-kernel, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
~lkcamp/patches, richard120310
Methods receive a slice and perform size check to add a valid way to make
conversion safe. An Option is used, in error case just return `None`.
The conversion between slices `[T]` is separated from others, because I
couldn't implement it in the same way as the other conversions.
Link: https://github.com/Rust-for-Linux/linux/issues/1119
Signed-off-by: Christian S. Lima <christiansantoslima21@gmail.com>
---
Changes in v2:
- Rollback the implementation for the macro in the repository and implement
methods in trait
- Link to v2: https://lore.kernel.org/rust-for-linux/20241012193657.290cc79c@eugeo/T/#t
Changes in v3:
- Fix grammar errors
- Remove repeated tests
- Fix alignment errors
- Fix tests not building
- Link to v3: https://lore.kernel.org/rust-for-linux/20241109055442.85190-1-christiansantoslima21@gmail.com/
Changes in v4:
- Removed core::simd::ToBytes
- Changed trait and methods to safe Add
- Result<&Self, Error> in order to make safe methods
- Link to v4: https://lore.kernel.org/rust-for-linux/20250314034910.134463-1-christiansantoslima21@gmail.com/
Changes in v5:
- Changed from Result to Option
- Removed commentaries
- Returned trait impl to unsafe
- Link to v5: https://lore.kernel.org/rust-for-linux/20250320014041.101470-1-christiansantoslima21@gmail.com/
Changes in v6:
- Add endianess check to doc test and use match to check
success case
- Reformulated safety comments
---
rust/kernel/transmute.rs | 89 +++++++++++++++++++++++++++++++++++++---
1 file changed, 83 insertions(+), 6 deletions(-)
diff --git a/rust/kernel/transmute.rs b/rust/kernel/transmute.rs
index 1c7d43771a37..16dfa5c7d467 100644
--- a/rust/kernel/transmute.rs
+++ b/rust/kernel/transmute.rs
@@ -9,29 +9,106 @@
///
/// It's okay for the type to have padding, as initializing those bytes has no effect.
///
+/// # Example
+/// ```
+/// let foo = &[1, 2, 3, 4];
+///
+/// let result = u32::from_bytes(foo);
+///
+/// #[cfg(target_endian = "little")]
+/// match result {
+/// Some(x) => assert_eq!(*x, 0x4030201),
+/// None => unreachable!()
+/// }
+///
+/// #[cfg(target_endian = "big")]
+/// match result {
+/// Some(x) => assert_eq!(*x, 0x1020304),
+/// None => unreachable!()
+/// }
+/// ```
+///
/// # Safety
///
/// All bit-patterns must be valid for this type. This type must not have interior mutability.
-pub unsafe trait FromBytes {}
+pub unsafe trait FromBytes {
+ /// Converts a slice of bytes to a reference to `Self` when possible.
+ fn from_bytes(bytes: &[u8]) -> Option<&Self>;
+
+ /// Converts a mutable slice of bytes to a reference to `Self` when possible.
+ fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
+ where
+ Self: AsBytes;
+}
macro_rules! impl_frombytes {
($($({$($generics:tt)*})? $t:ty, )*) => {
// SAFETY: Safety comments written in the macro invocation.
- $(unsafe impl$($($generics)*)? FromBytes for $t {})*
+ $(unsafe impl$($($generics)*)? FromBytes for $t {
+ fn from_bytes(bytes: &[u8]) -> Option<&$t> {
+ if bytes.len() == core::mem::size_of::<$t>() {
+ let slice_ptr = bytes.as_ptr().cast::<$t>();
+ unsafe { Some(&*slice_ptr) }
+ } else {
+ None
+ }
+ }
+
+ fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut $t>
+ where
+ Self: AsBytes,
+ {
+ if bytes.len() == core::mem::size_of::<$t>() {
+ let slice_ptr = bytes.as_mut_ptr().cast::<$t>();
+ unsafe { Some(&mut *slice_ptr) }
+ } else {
+ None
+ }
+ }
+ })*
};
}
impl_frombytes! {
// SAFETY: All bit patterns are acceptable values of the types below.
+ // Checking the pointer size makes this operation safe and it's necessary
+ // to dereference to get the value and return it as a reference to `Self`.
u8, u16, u32, u64, usize,
i8, i16, i32, i64, isize,
-
- // SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
- // patterns are also acceptable for arrays of that type.
- {<T: FromBytes>} [T],
{<T: FromBytes, const N: usize>} [T; N],
}
+// SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
+// patterns are also acceptable for arrays of that type.
+unsafe impl<T: FromBytes> FromBytes for [T] {
+ fn from_bytes(bytes: &[u8]) -> Option<&Self> {
+ let slice_ptr = bytes.as_ptr().cast::<T>();
+ if bytes.len() % core::mem::size_of::<T>() == 0 {
+ let slice_len = bytes.len() / core::mem::size_of::<T>();
+ // SAFETY: Since the code checks the size and can be divided into blocks of size T
+ // the slice is valid because the size is multiple of T.
+ unsafe { Some(core::slice::from_raw_parts(slice_ptr, slice_len)) }
+ } else {
+ None
+ }
+ }
+
+ fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
+ where
+ Self: AsBytes,
+ {
+ let slice_ptr = bytes.as_mut_ptr().cast::<T>();
+ if bytes.len() % core::mem::size_of::<T>() == 0 {
+ let slice_len = bytes.len() / core::mem::size_of::<T>();
+ // SAFETY: Since the code checks the size and can be divided into blocks of size T
+ // the slice is valid because the size is multiple of T.
+ unsafe { Some(core::slice::from_raw_parts_mut(slice_ptr, slice_len)) }
+ } else {
+ None
+ }
+ }
+}
+
/// Types that can be viewed as an immutable slice of initialized bytes.
///
/// If a struct implements this trait, then it is okay to copy it byte-for-byte to userspace. This
--
2.49.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH] rust: transmute: Add methods for FromBytes trait
2025-03-30 23:40 [PATCH v6] rust: transmute: Add methods for FromBytes trait Christian S. Lima
@ 2025-03-30 23:40 ` Christian S. Lima
2025-03-31 10:50 ` Miguel Ojeda
2025-04-09 22:32 ` [PATCH v6] " Matthew Maurer
` (2 subsequent siblings)
3 siblings, 1 reply; 11+ messages in thread
From: Christian S. Lima @ 2025-03-30 23:40 UTC (permalink / raw)
To: rust-for-linux, linux-kernel, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
~lkcamp/patches, richard120310
Methods receive a slice and perform size check to add a valid way to make
conversion safe. An Option is used, in error case just return `None`.
The conversion between slices `[T]` is separated from others, because I
couldn't implement it in the same way as the other conversions.
Link: https://github.com/Rust-for-Linux/linux/issues/1119
Signed-off-by: Christian S. Lima <christiansantoslima21@gmail.com>
---
Changes in v2:
- Rollback the implementation for the macro in the repository and implement
methods in trait
- Link to v2: https://lore.kernel.org/rust-for-linux/20241012193657.290cc79c@eugeo/T/#t
Changes in v3:
- Fix grammar errors
- Remove repeated tests
- Fix alignment errors
- Fix tests not building
- Link to v3: https://lore.kernel.org/rust-for-linux/20241109055442.85190-1-christiansantoslima21@gmail.com/
Changes in v4:
- Removed core::simd::ToBytes
- Changed trait and methods to safe Add
- Result<&Self, Error> in order to make safe methods
- Link to v4: https://lore.kernel.org/rust-for-linux/20250314034910.134463-1-christiansantoslima21@gmail.com/
Changes in v5:
- Changed from Result to Option
- Removed commentaries
- Returned trait impl to unsafe
- Link to v5: https://lore.kernel.org/rust-for-linux/20250320014041.101470-1-christiansantoslima21@gmail.com/
Changes in v6:
- Add endianess check to doc test and use match to check
success case
- Reformulated safety comments
---
rust/kernel/transmute.rs | 89 +++++++++++++++++++++++++++++++++++++---
1 file changed, 83 insertions(+), 6 deletions(-)
diff --git a/rust/kernel/transmute.rs b/rust/kernel/transmute.rs
index 1c7d43771a37..16dfa5c7d467 100644
--- a/rust/kernel/transmute.rs
+++ b/rust/kernel/transmute.rs
@@ -9,29 +9,106 @@
///
/// It's okay for the type to have padding, as initializing those bytes has no effect.
///
+/// # Example
+/// ```
+/// let foo = &[1, 2, 3, 4];
+///
+/// let result = u32::from_bytes(foo);
+///
+/// #[cfg(target_endian = "little")]
+/// match result {
+/// Some(x) => assert_eq!(*x, 0x4030201),
+/// None => unreachable!()
+/// }
+///
+/// #[cfg(target_endian = "big")]
+/// match result {
+/// Some(x) => assert_eq!(*x, 0x1020304),
+/// None => unreachable!()
+/// }
+/// ```
+///
/// # Safety
///
/// All bit-patterns must be valid for this type. This type must not have interior mutability.
-pub unsafe trait FromBytes {}
+pub unsafe trait FromBytes {
+ /// Converts a slice of bytes to a reference to `Self` when possible.
+ fn from_bytes(bytes: &[u8]) -> Option<&Self>;
+
+ /// Converts a mutable slice of bytes to a reference to `Self` when possible.
+ fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
+ where
+ Self: AsBytes;
+}
macro_rules! impl_frombytes {
($($({$($generics:tt)*})? $t:ty, )*) => {
// SAFETY: Safety comments written in the macro invocation.
- $(unsafe impl$($($generics)*)? FromBytes for $t {})*
+ $(unsafe impl$($($generics)*)? FromBytes for $t {
+ fn from_bytes(bytes: &[u8]) -> Option<&$t> {
+ if bytes.len() == core::mem::size_of::<$t>() {
+ let slice_ptr = bytes.as_ptr().cast::<$t>();
+ unsafe { Some(&*slice_ptr) }
+ } else {
+ None
+ }
+ }
+
+ fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut $t>
+ where
+ Self: AsBytes,
+ {
+ if bytes.len() == core::mem::size_of::<$t>() {
+ let slice_ptr = bytes.as_mut_ptr().cast::<$t>();
+ unsafe { Some(&mut *slice_ptr) }
+ } else {
+ None
+ }
+ }
+ })*
};
}
impl_frombytes! {
// SAFETY: All bit patterns are acceptable values of the types below.
+ // Checking the pointer size makes this operation safe and it's necessary
+ // to dereference to get the value and return it as a reference to `Self`.
u8, u16, u32, u64, usize,
i8, i16, i32, i64, isize,
-
- // SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
- // patterns are also acceptable for arrays of that type.
- {<T: FromBytes>} [T],
{<T: FromBytes, const N: usize>} [T; N],
}
+// SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
+// patterns are also acceptable for arrays of that type.
+unsafe impl<T: FromBytes> FromBytes for [T] {
+ fn from_bytes(bytes: &[u8]) -> Option<&Self> {
+ let slice_ptr = bytes.as_ptr().cast::<T>();
+ if bytes.len() % core::mem::size_of::<T>() == 0 {
+ let slice_len = bytes.len() / core::mem::size_of::<T>();
+ // SAFETY: Since the code checks the size and can be divided into blocks of size T
+ // the slice is valid because the size is multiple of T.
+ unsafe { Some(core::slice::from_raw_parts(slice_ptr, slice_len)) }
+ } else {
+ None
+ }
+ }
+
+ fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
+ where
+ Self: AsBytes,
+ {
+ let slice_ptr = bytes.as_mut_ptr().cast::<T>();
+ if bytes.len() % core::mem::size_of::<T>() == 0 {
+ let slice_len = bytes.len() / core::mem::size_of::<T>();
+ // SAFETY: Since the code checks the size and can be divided into blocks of size T
+ // the slice is valid because the size is multiple of T.
+ unsafe { Some(core::slice::from_raw_parts_mut(slice_ptr, slice_len)) }
+ } else {
+ None
+ }
+ }
+}
+
/// Types that can be viewed as an immutable slice of initialized bytes.
///
/// If a struct implements this trait, then it is okay to copy it byte-for-byte to userspace. This
--
2.49.0
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH] rust: transmute: Add methods for FromBytes trait
2025-03-30 23:40 ` [PATCH] " Christian S. Lima
@ 2025-03-31 10:50 ` Miguel Ojeda
2025-03-31 18:18 ` Christian
0 siblings, 1 reply; 11+ messages in thread
From: Miguel Ojeda @ 2025-03-31 10:50 UTC (permalink / raw)
To: Christian S. Lima
Cc: rust-for-linux, linux-kernel, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
~lkcamp/patches, richard120310
On Mon, Mar 31, 2025 at 1:40 AM Christian S. Lima
<christiansantoslima21@gmail.com> wrote:
>
> Methods receive a slice and perform size check to add a valid way to make
> conversion safe. An Option is used, in error case just return `None`.
>
> The conversion between slices `[T]` is separated from others, because I
> couldn't implement it in the same way as the other conversions.
>
> Link: https://github.com/Rust-for-Linux/linux/issues/1119
> Signed-off-by: Christian S. Lima <christiansantoslima21@gmail.com>
Hmm... We got two emails, both with the essentially the same content,
1 second apart, the second one without the v6 in the title.
The one I am replying to is what seems to be the duplicate one.
Cheers,
Miguel
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] rust: transmute: Add methods for FromBytes trait
2025-03-31 10:50 ` Miguel Ojeda
@ 2025-03-31 18:18 ` Christian
2025-03-31 18:31 ` Miguel Ojeda
0 siblings, 1 reply; 11+ messages in thread
From: Christian @ 2025-03-31 18:18 UTC (permalink / raw)
To: Miguel Ojeda
Cc: rust-for-linux, linux-kernel, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich
Hi, Miguel. Idk what happened seems the git send-email took the commit
and the .patch together. Sorry about that and I forgot to reply all. :(
> The one I am replying to is what seems to be the duplicate one.
Should I submit another patch because of duplication?
Thanks,
Christian
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH] rust: transmute: Add methods for FromBytes trait
2025-03-31 18:18 ` Christian
@ 2025-03-31 18:31 ` Miguel Ojeda
0 siblings, 0 replies; 11+ messages in thread
From: Miguel Ojeda @ 2025-03-31 18:31 UTC (permalink / raw)
To: Christian
Cc: rust-for-linux, linux-kernel, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich
On Mon, Mar 31, 2025 at 8:18 PM Christian
<christiansantoslima21@gmail.com> wrote:
>
> Hi, Miguel. Idk what happened seems the git send-email took the commit
> and the .patch together. Sorry about that and I forgot to reply all. :(
>
> Should I submit another patch because of duplication?
No worries, there is no need to resend for that reason.
Thanks!
Cheers,
Miguel
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v6] rust: transmute: Add methods for FromBytes trait
2025-03-30 23:40 [PATCH v6] rust: transmute: Add methods for FromBytes trait Christian S. Lima
2025-03-30 23:40 ` [PATCH] " Christian S. Lima
@ 2025-04-09 22:32 ` Matthew Maurer
2025-04-09 23:01 ` Matthew Maurer
2025-04-14 19:54 ` Christian
2025-04-22 14:09 ` Alexandre Courbot
2025-05-28 19:46 ` Danilo Krummrich
3 siblings, 2 replies; 11+ messages in thread
From: Matthew Maurer @ 2025-04-09 22:32 UTC (permalink / raw)
To: Christian S. Lima
Cc: rust-for-linux, linux-kernel, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
~lkcamp/patches, richard120310
On Sun, Mar 30, 2025 at 4:40 PM Christian S. Lima
<christiansantoslima21@gmail.com> wrote:
>
> Methods receive a slice and perform size check to add a valid way to make
> conversion safe. An Option is used, in error case just return `None`.
>
> The conversion between slices `[T]` is separated from others, because I
> couldn't implement it in the same way as the other conversions.
>
> Link: https://github.com/Rust-for-Linux/linux/issues/1119
> Signed-off-by: Christian S. Lima <christiansantoslima21@gmail.com>
> ---
> Changes in v2:
> - Rollback the implementation for the macro in the repository and implement
> methods in trait
> - Link to v2: https://lore.kernel.org/rust-for-linux/20241012193657.290cc79c@eugeo/T/#t
>
> Changes in v3:
> - Fix grammar errors
> - Remove repeated tests
> - Fix alignment errors
> - Fix tests not building
> - Link to v3: https://lore.kernel.org/rust-for-linux/20241109055442.85190-1-christiansantoslima21@gmail.com/
>
> Changes in v4:
> - Removed core::simd::ToBytes
> - Changed trait and methods to safe Add
> - Result<&Self, Error> in order to make safe methods
> - Link to v4: https://lore.kernel.org/rust-for-linux/20250314034910.134463-1-christiansantoslima21@gmail.com/
>
> Changes in v5:
> - Changed from Result to Option
> - Removed commentaries
> - Returned trait impl to unsafe
> - Link to v5: https://lore.kernel.org/rust-for-linux/20250320014041.101470-1-christiansantoslima21@gmail.com/
>
> Changes in v6:
> - Add endianess check to doc test and use match to check
> success case
> - Reformulated safety comments
> ---
> rust/kernel/transmute.rs | 89 +++++++++++++++++++++++++++++++++++++---
> 1 file changed, 83 insertions(+), 6 deletions(-)
>
> diff --git a/rust/kernel/transmute.rs b/rust/kernel/transmute.rs
> index 1c7d43771a37..16dfa5c7d467 100644
> --- a/rust/kernel/transmute.rs
> +++ b/rust/kernel/transmute.rs
> @@ -9,29 +9,106 @@
> ///
> /// It's okay for the type to have padding, as initializing those bytes has no effect.
> ///
> +/// # Example
> +/// ```
> +/// let foo = &[1, 2, 3, 4];
> +///
> +/// let result = u32::from_bytes(foo);
> +///
> +/// #[cfg(target_endian = "little")]
> +/// match result {
> +/// Some(x) => assert_eq!(*x, 0x4030201),
> +/// None => unreachable!()
> +/// }
> +///
> +/// #[cfg(target_endian = "big")]
> +/// match result {
> +/// Some(x) => assert_eq!(*x, 0x1020304),
> +/// None => unreachable!()
> +/// }
> +/// ```
> +///
> /// # Safety
> ///
> /// All bit-patterns must be valid for this type. This type must not have interior mutability.
> -pub unsafe trait FromBytes {}
> +pub unsafe trait FromBytes {
> + /// Converts a slice of bytes to a reference to `Self` when possible.
> + fn from_bytes(bytes: &[u8]) -> Option<&Self>;
> +
> + /// Converts a mutable slice of bytes to a reference to `Self` when possible.
> + fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
> + where
> + Self: AsBytes;
> +}
>
> macro_rules! impl_frombytes {
> ($($({$($generics:tt)*})? $t:ty, )*) => {
> // SAFETY: Safety comments written in the macro invocation.
> - $(unsafe impl$($($generics)*)? FromBytes for $t {})*
> + $(unsafe impl$($($generics)*)? FromBytes for $t {
> + fn from_bytes(bytes: &[u8]) -> Option<&$t> {
Consider factoring this out into a helper function, e.g.
```
fn from_bytes_sized<T: FromBytes + Sized>(bytes: &[u8]) -> Option<&T> {
```
which you can then call in here. If you were not trying to handle
`?Sized`, we could even put it in the trait default implementation.
> + if bytes.len() == core::mem::size_of::<$t>() {
> + let slice_ptr = bytes.as_ptr().cast::<$t>();
There's no alignment check, and so the resulting constructed reference
may be misaligned, which is UB. Same below.
> + unsafe { Some(&*slice_ptr) }
> + } else {
> + None
> + }
> + }
> +
> + fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut $t>
> + where
> + Self: AsBytes,
> + {
> + if bytes.len() == core::mem::size_of::<$t>() {
> + let slice_ptr = bytes.as_mut_ptr().cast::<$t>();
> + unsafe { Some(&mut *slice_ptr) }
> + } else {
> + None
> + }
> + }
> + })*
> };
> }
>
> impl_frombytes! {
> // SAFETY: All bit patterns are acceptable values of the types below.
> + // Checking the pointer size makes this operation safe and it's necessary
> + // to dereference to get the value and return it as a reference to `Self`.
> u8, u16, u32, u64, usize,
> i8, i16, i32, i64, isize,
> -
> - // SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
> - // patterns are also acceptable for arrays of that type.
> - {<T: FromBytes>} [T],
> {<T: FromBytes, const N: usize>} [T; N],
> }
>
> +// SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
> +// patterns are also acceptable for arrays of that type.
> +unsafe impl<T: FromBytes> FromBytes for [T] {
> + fn from_bytes(bytes: &[u8]) -> Option<&Self> {
> + let slice_ptr = bytes.as_ptr().cast::<T>();
> + if bytes.len() % core::mem::size_of::<T>() == 0 {
> + let slice_len = bytes.len() / core::mem::size_of::<T>();
> + // SAFETY: Since the code checks the size and can be divided into blocks of size T
> + // the slice is valid because the size is multiple of T.
> + unsafe { Some(core::slice::from_raw_parts(slice_ptr, slice_len)) }
> + } else {
> + None
> + }
> + }
> +
> + fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
> + where
> + Self: AsBytes,
> + {
> + let slice_ptr = bytes.as_mut_ptr().cast::<T>();
> + if bytes.len() % core::mem::size_of::<T>() == 0 {
> + let slice_len = bytes.len() / core::mem::size_of::<T>();
> + // SAFETY: Since the code checks the size and can be divided into blocks of size T
> + // the slice is valid because the size is multiple of T.
> + unsafe { Some(core::slice::from_raw_parts_mut(slice_ptr, slice_len)) }
> + } else {
> + None
> + }
> + }
> +}
> +
> /// Types that can be viewed as an immutable slice of initialized bytes.
> ///
> /// If a struct implements this trait, then it is okay to copy it byte-for-byte to userspace. This
> --
> 2.49.0
>
>
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v6] rust: transmute: Add methods for FromBytes trait
2025-04-09 22:32 ` [PATCH v6] " Matthew Maurer
@ 2025-04-09 23:01 ` Matthew Maurer
2025-04-14 19:54 ` Christian
1 sibling, 0 replies; 11+ messages in thread
From: Matthew Maurer @ 2025-04-09 23:01 UTC (permalink / raw)
To: Christian S. Lima
Cc: rust-for-linux, linux-kernel, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
~lkcamp/patches, richard120310
On Wed, Apr 9, 2025 at 3:32 PM Matthew Maurer <mmaurer@google.com> wrote:
>
> On Sun, Mar 30, 2025 at 4:40 PM Christian S. Lima
> <christiansantoslima21@gmail.com> wrote:
> >
> > Methods receive a slice and perform size check to add a valid way to make
> > conversion safe. An Option is used, in error case just return `None`.
> >
> > The conversion between slices `[T]` is separated from others, because I
> > couldn't implement it in the same way as the other conversions.
> >
> > Link: https://github.com/Rust-for-Linux/linux/issues/1119
> > Signed-off-by: Christian S. Lima <christiansantoslima21@gmail.com>
> > ---
> > Changes in v2:
> > - Rollback the implementation for the macro in the repository and implement
> > methods in trait
> > - Link to v2: https://lore.kernel.org/rust-for-linux/20241012193657.290cc79c@eugeo/T/#t
> >
> > Changes in v3:
> > - Fix grammar errors
> > - Remove repeated tests
> > - Fix alignment errors
> > - Fix tests not building
> > - Link to v3: https://lore.kernel.org/rust-for-linux/20241109055442.85190-1-christiansantoslima21@gmail.com/
> >
> > Changes in v4:
> > - Removed core::simd::ToBytes
> > - Changed trait and methods to safe Add
> > - Result<&Self, Error> in order to make safe methods
> > - Link to v4: https://lore.kernel.org/rust-for-linux/20250314034910.134463-1-christiansantoslima21@gmail.com/
> >
> > Changes in v5:
> > - Changed from Result to Option
> > - Removed commentaries
> > - Returned trait impl to unsafe
> > - Link to v5: https://lore.kernel.org/rust-for-linux/20250320014041.101470-1-christiansantoslima21@gmail.com/
> >
> > Changes in v6:
> > - Add endianess check to doc test and use match to check
> > success case
> > - Reformulated safety comments
> > ---
> > rust/kernel/transmute.rs | 89 +++++++++++++++++++++++++++++++++++++---
> > 1 file changed, 83 insertions(+), 6 deletions(-)
> >
> > diff --git a/rust/kernel/transmute.rs b/rust/kernel/transmute.rs
> > index 1c7d43771a37..16dfa5c7d467 100644
> > --- a/rust/kernel/transmute.rs
> > +++ b/rust/kernel/transmute.rs
> > @@ -9,29 +9,106 @@
> > ///
> > /// It's okay for the type to have padding, as initializing those bytes has no effect.
> > ///
> > +/// # Example
> > +/// ```
> > +/// let foo = &[1, 2, 3, 4];
> > +///
> > +/// let result = u32::from_bytes(foo);
> > +///
> > +/// #[cfg(target_endian = "little")]
> > +/// match result {
> > +/// Some(x) => assert_eq!(*x, 0x4030201),
> > +/// None => unreachable!()
> > +/// }
> > +///
> > +/// #[cfg(target_endian = "big")]
> > +/// match result {
> > +/// Some(x) => assert_eq!(*x, 0x1020304),
> > +/// None => unreachable!()
> > +/// }
> > +/// ```
> > +///
> > /// # Safety
> > ///
> > /// All bit-patterns must be valid for this type. This type must not have interior mutability.
> > -pub unsafe trait FromBytes {}
> > +pub unsafe trait FromBytes {
> > + /// Converts a slice of bytes to a reference to `Self` when possible.
> > + fn from_bytes(bytes: &[u8]) -> Option<&Self>;
> > +
> > + /// Converts a mutable slice of bytes to a reference to `Self` when possible.
> > + fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
> > + where
> > + Self: AsBytes;
> > +}
> >
> > macro_rules! impl_frombytes {
> > ($($({$($generics:tt)*})? $t:ty, )*) => {
> > // SAFETY: Safety comments written in the macro invocation.
> > - $(unsafe impl$($($generics)*)? FromBytes for $t {})*
> > + $(unsafe impl$($($generics)*)? FromBytes for $t {
> > + fn from_bytes(bytes: &[u8]) -> Option<&$t> {
>
> Consider factoring this out into a helper function, e.g.
> ```
> fn from_bytes_sized<T: FromBytes + Sized>(bytes: &[u8]) -> Option<&T> {
> ```
> which you can then call in here. If you were not trying to handle
> `?Sized`, we could even put it in the trait default implementation.
>
> > + if bytes.len() == core::mem::size_of::<$t>() {
> > + let slice_ptr = bytes.as_ptr().cast::<$t>();
>
> There's no alignment check, and so the resulting constructed reference
> may be misaligned, which is UB. Same below.
>
> > + unsafe { Some(&*slice_ptr) }
> > + } else {
> > + None
> > + }
> > + }
> > +
> > + fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut $t>
Sorry, one last thing - could we consider `from_mut_bytes` instead of
`from_bytes_mut` to match the current API of `zerocopy`?
> > + where
> > + Self: AsBytes,
> > + {
> > + if bytes.len() == core::mem::size_of::<$t>() {
> > + let slice_ptr = bytes.as_mut_ptr().cast::<$t>();
> > + unsafe { Some(&mut *slice_ptr) }
> > + } else {
> > + None
> > + }
> > + }
> > + })*
> > };
> > }
> >
> > impl_frombytes! {
> > // SAFETY: All bit patterns are acceptable values of the types below.
> > + // Checking the pointer size makes this operation safe and it's necessary
> > + // to dereference to get the value and return it as a reference to `Self`.
> > u8, u16, u32, u64, usize,
> > i8, i16, i32, i64, isize,
> > -
> > - // SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
> > - // patterns are also acceptable for arrays of that type.
> > - {<T: FromBytes>} [T],
> > {<T: FromBytes, const N: usize>} [T; N],
> > }
> >
> > +// SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
> > +// patterns are also acceptable for arrays of that type.
> > +unsafe impl<T: FromBytes> FromBytes for [T] {
> > + fn from_bytes(bytes: &[u8]) -> Option<&Self> {
> > + let slice_ptr = bytes.as_ptr().cast::<T>();
> > + if bytes.len() % core::mem::size_of::<T>() == 0 {
> > + let slice_len = bytes.len() / core::mem::size_of::<T>();
> > + // SAFETY: Since the code checks the size and can be divided into blocks of size T
> > + // the slice is valid because the size is multiple of T.
> > + unsafe { Some(core::slice::from_raw_parts(slice_ptr, slice_len)) }
> > + } else {
> > + None
> > + }
> > + }
> > +
> > + fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
> > + where
> > + Self: AsBytes,
> > + {
> > + let slice_ptr = bytes.as_mut_ptr().cast::<T>();
> > + if bytes.len() % core::mem::size_of::<T>() == 0 {
> > + let slice_len = bytes.len() / core::mem::size_of::<T>();
> > + // SAFETY: Since the code checks the size and can be divided into blocks of size T
> > + // the slice is valid because the size is multiple of T.
> > + unsafe { Some(core::slice::from_raw_parts_mut(slice_ptr, slice_len)) }
> > + } else {
> > + None
> > + }
> > + }
> > +}
> > +
> > /// Types that can be viewed as an immutable slice of initialized bytes.
> > ///
> > /// If a struct implements this trait, then it is okay to copy it byte-for-byte to userspace. This
> > --
> > 2.49.0
> >
> >
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v6] rust: transmute: Add methods for FromBytes trait
2025-04-09 22:32 ` [PATCH v6] " Matthew Maurer
2025-04-09 23:01 ` Matthew Maurer
@ 2025-04-14 19:54 ` Christian
1 sibling, 0 replies; 11+ messages in thread
From: Christian @ 2025-04-14 19:54 UTC (permalink / raw)
To: Matthew Maurer
Cc: rust-for-linux, linux-kernel, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
~lkcamp/patches, richard120310
> Consider factoring this out into a helper function, e.g.
> ```
> fn from_bytes_sized<T: FromBytes + Sized>(bytes: &[u8]) -> Option<&T> {
> ```
> which you can then call in here. If you were not trying to handle
> `?Sized`, we could even put it in the trait default implementation.
What do you think about
```
fn from_bytes(bytes: &[u8]) -> Option<&Self>
where:
Self: Sized
```
for the default implementation?
> > + if bytes.len() == core::mem::size_of::<$t>() {
> > + let slice_ptr = bytes.as_ptr().cast::<$t>();
>
> There's no alignment check, and so the resulting constructed reference
> may be misaligned, which is UB. Same below.
I see, I didn't think about it. Good catch and thanks for the tip!
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v6] rust: transmute: Add methods for FromBytes trait
2025-03-30 23:40 [PATCH v6] rust: transmute: Add methods for FromBytes trait Christian S. Lima
2025-03-30 23:40 ` [PATCH] " Christian S. Lima
2025-04-09 22:32 ` [PATCH v6] " Matthew Maurer
@ 2025-04-22 14:09 ` Alexandre Courbot
2025-05-28 19:46 ` Danilo Krummrich
3 siblings, 0 replies; 11+ messages in thread
From: Alexandre Courbot @ 2025-04-22 14:09 UTC (permalink / raw)
To: Christian S. Lima, rust-for-linux, linux-kernel, Miguel Ojeda,
Alex Gaynor, Boqun Feng, Gary Guo, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Alice Ryhl, Trevor Gross,
Danilo Krummrich, ~lkcamp/patches, richard120310
On Mon Mar 31, 2025 at 8:40 AM JST, Christian S. Lima wrote:
> Methods receive a slice and perform size check to add a valid way to make
> conversion safe. An Option is used, in error case just return `None`.
>
> The conversion between slices `[T]` is separated from others, because I
> couldn't implement it in the same way as the other conversions.
>
> Link: https://github.com/Rust-for-Linux/linux/issues/1119
> Signed-off-by: Christian S. Lima <christiansantoslima21@gmail.com>
> ---
> Changes in v2:
> - Rollback the implementation for the macro in the repository and implement
> methods in trait
> - Link to v2: https://lore.kernel.org/rust-for-linux/20241012193657.290cc79c@eugeo/T/#t
>
> Changes in v3:
> - Fix grammar errors
> - Remove repeated tests
> - Fix alignment errors
> - Fix tests not building
> - Link to v3: https://lore.kernel.org/rust-for-linux/20241109055442.85190-1-christiansantoslima21@gmail.com/
>
> Changes in v4:
> - Removed core::simd::ToBytes
> - Changed trait and methods to safe Add
> - Result<&Self, Error> in order to make safe methods
> - Link to v4: https://lore.kernel.org/rust-for-linux/20250314034910.134463-1-christiansantoslima21@gmail.com/
>
> Changes in v5:
> - Changed from Result to Option
> - Removed commentaries
> - Returned trait impl to unsafe
> - Link to v5: https://lore.kernel.org/rust-for-linux/20250320014041.101470-1-christiansantoslima21@gmail.com/
>
> Changes in v6:
> - Add endianess check to doc test and use match to check
> success case
> - Reformulated safety comments
> ---
> rust/kernel/transmute.rs | 89 +++++++++++++++++++++++++++++++++++++---
> 1 file changed, 83 insertions(+), 6 deletions(-)
>
> diff --git a/rust/kernel/transmute.rs b/rust/kernel/transmute.rs
> index 1c7d43771a37..16dfa5c7d467 100644
> --- a/rust/kernel/transmute.rs
> +++ b/rust/kernel/transmute.rs
> @@ -9,29 +9,106 @@
> ///
> /// It's okay for the type to have padding, as initializing those bytes has no effect.
> ///
> +/// # Example
> +/// ```
> +/// let foo = &[1, 2, 3, 4];
> +///
> +/// let result = u32::from_bytes(foo);
> +///
> +/// #[cfg(target_endian = "little")]
> +/// match result {
> +/// Some(x) => assert_eq!(*x, 0x4030201),
> +/// None => unreachable!()
> +/// }
> +///
> +/// #[cfg(target_endian = "big")]
> +/// match result {
> +/// Some(x) => assert_eq!(*x, 0x1020304),
> +/// None => unreachable!()
> +/// }
> +/// ```
> +///
> /// # Safety
> ///
> /// All bit-patterns must be valid for this type. This type must not have interior mutability.
> -pub unsafe trait FromBytes {}
> +pub unsafe trait FromBytes {
> + /// Converts a slice of bytes to a reference to `Self` when possible.
> + fn from_bytes(bytes: &[u8]) -> Option<&Self>;
> +
> + /// Converts a mutable slice of bytes to a reference to `Self` when possible.
> + fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
> + where
> + Self: AsBytes;
> +}
>
> macro_rules! impl_frombytes {
> ($($({$($generics:tt)*})? $t:ty, )*) => {
> // SAFETY: Safety comments written in the macro invocation.
> - $(unsafe impl$($($generics)*)? FromBytes for $t {})*
> + $(unsafe impl$($($generics)*)? FromBytes for $t {
> + fn from_bytes(bytes: &[u8]) -> Option<&$t> {
> + if bytes.len() == core::mem::size_of::<$t>() {
> + let slice_ptr = bytes.as_ptr().cast::<$t>();
> + unsafe { Some(&*slice_ptr) }
> + } else {
> + None
> + }
> + }
This is probably a naive question, but is there a reason why this cannot
be the default implementation of `from_bytes`? IIUC other implementors
would have to come with their own implementation, which adds an extra
burden.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v6] rust: transmute: Add methods for FromBytes trait
2025-03-30 23:40 [PATCH v6] rust: transmute: Add methods for FromBytes trait Christian S. Lima
` (2 preceding siblings ...)
2025-04-22 14:09 ` Alexandre Courbot
@ 2025-05-28 19:46 ` Danilo Krummrich
2025-06-09 4:33 ` Christian
3 siblings, 1 reply; 11+ messages in thread
From: Danilo Krummrich @ 2025-05-28 19:46 UTC (permalink / raw)
To: Christian S. Lima
Cc: rust-for-linux, linux-kernel, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, ~lkcamp/patches,
richard120310
Hi Christian,
On Sun, Mar 30, 2025 at 08:40:15PM -0300, Christian S. Lima wrote:
> Methods receive a slice and perform size check to add a valid way to make
> conversion safe. An Option is used, in error case just return `None`.
>
> The conversion between slices `[T]` is separated from others, because I
> couldn't implement it in the same way as the other conversions.
>
> Link: https://github.com/Rust-for-Linux/linux/issues/1119
> Signed-off-by: Christian S. Lima <christiansantoslima21@gmail.com>
What's the status of the series? Are you still working on this topic?
- Danilo
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH v6] rust: transmute: Add methods for FromBytes trait
2025-05-28 19:46 ` Danilo Krummrich
@ 2025-06-09 4:33 ` Christian
0 siblings, 0 replies; 11+ messages in thread
From: Christian @ 2025-06-09 4:33 UTC (permalink / raw)
To: Danilo Krummrich
Cc: rust-for-linux, linux-kernel, Miguel Ojeda, Alex Gaynor,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Alice Ryhl, Trevor Gross, ~lkcamp/patches,
richard120310
> What's the status of the series? Are you still working on this topic
Hi Danilo, I'm currently working on the alignment issue that was
mentioned in that email. I'm still working on it, and I'll send a
patch this week.
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2025-06-09 4:33 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-03-30 23:40 [PATCH v6] rust: transmute: Add methods for FromBytes trait Christian S. Lima
2025-03-30 23:40 ` [PATCH] " Christian S. Lima
2025-03-31 10:50 ` Miguel Ojeda
2025-03-31 18:18 ` Christian
2025-03-31 18:31 ` Miguel Ojeda
2025-04-09 22:32 ` [PATCH v6] " Matthew Maurer
2025-04-09 23:01 ` Matthew Maurer
2025-04-14 19:54 ` Christian
2025-04-22 14:09 ` Alexandre Courbot
2025-05-28 19:46 ` Danilo Krummrich
2025-06-09 4:33 ` Christian
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).