drivers/android/binder/thread.rs | 14 +++++--------- init/Kconfig | 3 +++ rust/kernel/lib.rs | 1 + rust/kernel/prelude.rs | 3 +++ rust/kernel/usize_ext.rs | 30 ++++++++++++++++++++++++++++++ 5 files changed, 42 insertions(+), 9 deletions(-)
From: KaiserGranatapfel <christopher.erleigh@gmail.com>
Remove the local `is_aligned` helper from the binder thread module and
replace all call sites with `usize::is_multiple_of`, which is the
idiomatic Rust API for checking divisibility.
Since `is_multiple_of` was only stabilized in Rust 1.87.0 and the
kernel MSRV is currently 1.78.0, introduce a `UsizeExt` extension
trait in `rust/kernel/usize_ext.rs` as a polyfill. The trait is
conditionally compiled behind `CONFIG_RUSTC_HAS_USIZE_IS_MULTIPLE_OF`
(set when rustc >= 1.87.0) and re-exported via the kernel prelude,
following the same pattern used for `AsFlattened` / `slice_flatten`.
The `offset % type_size == 0` expression in `rust/kernel/io.rs` is
intentionally left unchanged as it lives inside a `const fn` where
trait method calls are not permitted.
Link: https://github.com/Rust-for-Linux/linux/issues/1220
Signed-off-by: Christopher Erleigh (KaiserGranatapfel) <christopher.erleigh@gmail.com>
---
The recently landed patch "rust_binder: add additional alignment checks"
introduced a local `is_aligned` helper as a workaround for
`usize::is_multiple_of` not being available prior to Rust 1.87.0.
This patch replaces that helper with a `UsizeExt` extension trait that
provides `is_multiple_of` as a polyfill, following the same pattern used
for `AsFlattened` / `slice_flatten`. The trait is gated behind
`CONFIG_RUSTC_HAS_USIZE_IS_MULTIPLE_OF` and will become a no-op once
the kernel MSRV reaches 1.87.0.
Note: the From: header uses my GitHub username "KaiserGranatapfel", as
this is tied to my Git and GitHub identity. My real name is Christopher
Erleigh, as reflected in the Signed-off-by trailer.
---
drivers/android/binder/thread.rs | 14 +++++---------
init/Kconfig | 3 +++
rust/kernel/lib.rs | 1 +
rust/kernel/prelude.rs | 3 +++
rust/kernel/usize_ext.rs | 30 ++++++++++++++++++++++++++++++
5 files changed, 42 insertions(+), 9 deletions(-)
diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
index 0b62d24b2..25d499d05 100644
--- a/drivers/android/binder/thread.rs
+++ b/drivers/android/binder/thread.rs
@@ -36,10 +36,6 @@
use core::mem::size_of;
-fn is_aligned(value: usize, to: usize) -> bool {
- value % to == 0
-}
-
/// Stores the layout of the scatter-gather entries. This is used during the `translate_objects`
/// call and is discarded when it returns.
struct ScatterGatherState {
@@ -796,7 +792,7 @@ fn translate_object(
let num_fds = usize::try_from(obj.num_fds).map_err(|_| EINVAL)?;
let fds_len = num_fds.checked_mul(size_of::<u32>()).ok_or(EINVAL)?;
- if !is_aligned(parent_offset, size_of::<u32>()) {
+ if !parent_offset.is_multiple_of(size_of::<u32>()) {
return Err(EINVAL.into());
}
@@ -814,7 +810,7 @@ fn translate_object(
}
};
- if !is_aligned(parent_entry.sender_uaddr, size_of::<u32>()) {
+ if !parent_entry.sender_uaddr.is_multiple_of(size_of::<u32>()) {
return Err(EINVAL.into());
}
@@ -975,10 +971,10 @@ pub(crate) fn copy_transaction_data(
None => 0,
};
- if !is_aligned(offsets_size, size_of::<u64>()) {
+ if !offsets_size.is_multiple_of(size_of::<u64>()) {
return Err(EINVAL.into());
}
- if !is_aligned(buffers_size, size_of::<u64>()) {
+ if !buffers_size.is_multiple_of(size_of::<u64>()) {
return Err(EINVAL.into());
}
@@ -1047,7 +1043,7 @@ pub(crate) fn copy_transaction_data(
.try_into()
.map_err(|_| EINVAL)?;
- if offset < end_of_previous_object || !is_aligned(offset, size_of::<u32>()) {
+ if offset < end_of_previous_object || !offset.is_multiple_of(size_of::<u32>()) {
pr_warn!("Got transaction with invalid offset.");
return Err(EINVAL.into());
}
diff --git a/init/Kconfig b/init/Kconfig
index b55deae92..bd7493480 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -166,6 +166,9 @@ config LD_CAN_USE_KEEP_IN_OVERLAY
config RUSTC_HAS_SLICE_AS_FLATTENED
def_bool RUSTC_VERSION >= 108000
+config RUSTC_HAS_USIZE_IS_MULTIPLE_OF
+ def_bool RUSTC_VERSION >= 108700
+
config RUSTC_HAS_COERCE_POINTEE
def_bool RUSTC_VERSION >= 108400
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 3da92f18f..59216912a 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -157,6 +157,7 @@
pub mod uaccess;
#[cfg(CONFIG_USB = "y")]
pub mod usb;
+pub mod usize_ext;
pub mod workqueue;
pub mod xarray;
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index 2877e3f7b..7e778a666 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -53,3 +53,6 @@
#[cfg(not(CONFIG_RUSTC_HAS_SLICE_AS_FLATTENED))]
pub use super::slice::AsFlattened;
+
+#[cfg(not(CONFIG_RUSTC_HAS_USIZE_IS_MULTIPLE_OF))]
+pub use super::usize_ext::UsizeExt as _;
diff --git a/rust/kernel/usize_ext.rs b/rust/kernel/usize_ext.rs
new file mode 100644
index 000000000..690265bc0
--- /dev/null
+++ b/rust/kernel/usize_ext.rs
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Additional (and temporary) `usize` helpers.
+
+/// Extension trait providing a portable version of [`usize::is_multiple_of`].
+///
+/// `usize::is_multiple_of` was stabilized in Rust 1.87.0. This extension trait
+/// provides the same functionality for kernels built with older toolchains.
+///
+/// This trait can be removed once the MSRV passes 1.87.
+///
+/// [`usize::is_multiple_of`]: https://doc.rust-lang.org/std/primitive.usize.html#method.is_multiple_of
+#[cfg(not(CONFIG_RUSTC_HAS_USIZE_IS_MULTIPLE_OF))]
+pub trait UsizeExt {
+ /// Returns `true` if `self` is a multiple of `rhs`.
+ ///
+ /// This is a portable layer on top of [`usize::is_multiple_of`]; see its documentation for
+ /// details.
+ ///
+ /// [`usize::is_multiple_of`]: https://doc.rust-lang.org/std/primitive.usize.html#method.is_multiple_of
+ fn is_multiple_of(self, rhs: usize) -> bool;
+}
+
+#[cfg(not(CONFIG_RUSTC_HAS_USIZE_IS_MULTIPLE_OF))]
+impl UsizeExt for usize {
+ #[inline]
+ fn is_multiple_of(self, rhs: usize) -> bool {
+ self % rhs == 0
+ }
+}
---
base-commit: 11439c4635edd669ae435eec308f4ab8a0804808
change-id: 20260302-rust-binder-is-multiple-of-2d757cf0a70f
Best regards,
--
KaiserGranatapfel <christopher.erleigh@gmail.com>
On Mon, Mar 02, 2026 at 09:35:52PM +0200, KaiserGranatapfel via B4 Relay wrote: > From: KaiserGranatapfel <christopher.erleigh@gmail.com> Does not match the signed-off-by line :(
On Mon Mar 2, 2026 at 7:35 PM GMT, KaiserGranatapfel via B4 Relay wrote:
> From: KaiserGranatapfel <christopher.erleigh@gmail.com>
>
> Remove the local `is_aligned` helper from the binder thread module and
> replace all call sites with `usize::is_multiple_of`, which is the
> idiomatic Rust API for checking divisibility.
>
> Since `is_multiple_of` was only stabilized in Rust 1.87.0 and the
> kernel MSRV is currently 1.78.0, introduce a `UsizeExt` extension
> trait in `rust/kernel/usize_ext.rs` as a polyfill. The trait is
> conditionally compiled behind `CONFIG_RUSTC_HAS_USIZE_IS_MULTIPLE_OF`
> (set when rustc >= 1.87.0) and re-exported via the kernel prelude,
> following the same pattern used for `AsFlattened` / `slice_flatten`.
>
> The `offset % type_size == 0` expression in `rust/kernel/io.rs` is
> intentionally left unchanged as it lives inside a `const fn` where
> trait method calls are not permitted.
>
> Link: https://github.com/Rust-for-Linux/linux/issues/1220
> Signed-off-by: Christopher Erleigh (KaiserGranatapfel) <christopher.erleigh@gmail.com>
> ---
> The recently landed patch "rust_binder: add additional alignment checks"
> introduced a local `is_aligned` helper as a workaround for
> `usize::is_multiple_of` not being available prior to Rust 1.87.0.
>
> This patch replaces that helper with a `UsizeExt` extension trait that
> provides `is_multiple_of` as a polyfill, following the same pattern used
> for `AsFlattened` / `slice_flatten`. The trait is gated behind
> `CONFIG_RUSTC_HAS_USIZE_IS_MULTIPLE_OF` and will become a no-op once
> the kernel MSRV reaches 1.87.0.
We should start using the feature unstably as soon as 1.82. Whether a feature is
stable in a specific version doesn't matter for the kernel, we can use it as
long as it's available unstably and is stable in latest Rust version.
AsFlattened is special as it's renamed during stabilization, so we don't have a
version that can have the feature enabled.
>
> Note: the From: header uses my GitHub username "KaiserGranatapfel", as
GitHub associates commits with user handles via email address. You should just
use your name in the S-o-b and commits (From header).
Best,
Gary
> this is tied to my Git and GitHub identity. My real name is Christopher
> Erleigh, as reflected in the Signed-off-by trailer.
> ---
> drivers/android/binder/thread.rs | 14 +++++---------
> init/Kconfig | 3 +++
> rust/kernel/lib.rs | 1 +A
> rust/kernel/prelude.rs | 3 +++
> rust/kernel/usize_ext.rs | 30 ++++++++++++++++++++++++++++++
> 5 files changed, 42 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/android/binder/thread.rs b/drivers/android/binder/thread.rs
> index 0b62d24b2..25d499d05 100644
> --- a/drivers/android/binder/thread.rs
> +++ b/drivers/android/binder/thread.rs
> @@ -36,10 +36,6 @@
>
> use core::mem::size_of;
>
> -fn is_aligned(value: usize, to: usize) -> bool {
> - value % to == 0
> -}
> -
> /// Stores the layout of the scatter-gather entries. This is used during the `translate_objects`
> /// call and is discarded when it returns.
> struct ScatterGatherState {
> @@ -796,7 +792,7 @@ fn translate_object(
> let num_fds = usize::try_from(obj.num_fds).map_err(|_| EINVAL)?;
> let fds_len = num_fds.checked_mul(size_of::<u32>()).ok_or(EINVAL)?;
>
> - if !is_aligned(parent_offset, size_of::<u32>()) {
> + if !parent_offset.is_multiple_of(size_of::<u32>()) {
> return Err(EINVAL.into());
> }
>
> @@ -814,7 +810,7 @@ fn translate_object(
> }
> };
>
> - if !is_aligned(parent_entry.sender_uaddr, size_of::<u32>()) {
> + if !parent_entry.sender_uaddr.is_multiple_of(size_of::<u32>()) {
> return Err(EINVAL.into());
> }
>
> @@ -975,10 +971,10 @@ pub(crate) fn copy_transaction_data(
> None => 0,
> };
>
> - if !is_aligned(offsets_size, size_of::<u64>()) {
> + if !offsets_size.is_multiple_of(size_of::<u64>()) {
> return Err(EINVAL.into());
> }
> - if !is_aligned(buffers_size, size_of::<u64>()) {
> + if !buffers_size.is_multiple_of(size_of::<u64>()) {
> return Err(EINVAL.into());
> }
>
> @@ -1047,7 +1043,7 @@ pub(crate) fn copy_transaction_data(
> .try_into()
> .map_err(|_| EINVAL)?;
>
> - if offset < end_of_previous_object || !is_aligned(offset, size_of::<u32>()) {
> + if offset < end_of_previous_object || !offset.is_multiple_of(size_of::<u32>()) {
> pr_warn!("Got transaction with invalid offset.");
> return Err(EINVAL.into());
> }
> diff --git a/init/Kconfig b/init/Kconfig
> index b55deae92..bd7493480 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -166,6 +166,9 @@ config LD_CAN_USE_KEEP_IN_OVERLAY
> config RUSTC_HAS_SLICE_AS_FLATTENED
> def_bool RUSTC_VERSION >= 108000
>
> +config RUSTC_HAS_USIZE_IS_MULTIPLE_OF
> + def_bool RUSTC_VERSION >= 108700
> +
> config RUSTC_HAS_COERCE_POINTEE
> def_bool RUSTC_VERSION >= 108400
>
> diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
> index 3da92f18f..59216912a 100644
> --- a/rust/kernel/lib.rs
> +++ b/rust/kernel/lib.rs
> @@ -157,6 +157,7 @@
> pub mod uaccess;
> #[cfg(CONFIG_USB = "y")]
> pub mod usb;
> +pub mod usize_ext;
> pub mod workqueue;
> pub mod xarray;
>
> diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
> index 2877e3f7b..7e778a666 100644
> --- a/rust/kernel/prelude.rs
> +++ b/rust/kernel/prelude.rs
> @@ -53,3 +53,6 @@
>
> #[cfg(not(CONFIG_RUSTC_HAS_SLICE_AS_FLATTENED))]
> pub use super::slice::AsFlattened;
> +
> +#[cfg(not(CONFIG_RUSTC_HAS_USIZE_IS_MULTIPLE_OF))]
> +pub use super::usize_ext::UsizeExt as _;
> diff --git a/rust/kernel/usize_ext.rs b/rust/kernel/usize_ext.rs
> new file mode 100644
> index 000000000..690265bc0
> --- /dev/null
> +++ b/rust/kernel/usize_ext.rs
> @@ -0,0 +1,30 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +//! Additional (and temporary) `usize` helpers.
> +
> +/// Extension trait providing a portable version of [`usize::is_multiple_of`].
> +///
> +/// `usize::is_multiple_of` was stabilized in Rust 1.87.0. This extension trait
> +/// provides the same functionality for kernels built with older toolchains.
> +///
> +/// This trait can be removed once the MSRV passes 1.87.
> +///
> +/// [`usize::is_multiple_of`]: https://doc.rust-lang.org/std/primitive.usize.html#method.is_multiple_of
> +#[cfg(not(CONFIG_RUSTC_HAS_USIZE_IS_MULTIPLE_OF))]
> +pub trait UsizeExt {
> + /// Returns `true` if `self` is a multiple of `rhs`.
> + ///
> + /// This is a portable layer on top of [`usize::is_multiple_of`]; see its documentation for
> + /// details.
> + ///
> + /// [`usize::is_multiple_of`]: https://doc.rust-lang.org/std/primitive.usize.html#method.is_multiple_of
> + fn is_multiple_of(self, rhs: usize) -> bool;
> +}
> +
> +#[cfg(not(CONFIG_RUSTC_HAS_USIZE_IS_MULTIPLE_OF))]
> +impl UsizeExt for usize {
> + #[inline]
> + fn is_multiple_of(self, rhs: usize) -> bool {
> + self % rhs == 0
> + }
> +}
>
> ---
> base-commit: 11439c4635edd669ae435eec308f4ab8a0804808
> change-id: 20260302-rust-binder-is-multiple-of-2d757cf0a70f
>
> Best regards,
© 2016 - 2026 Red Hat, Inc.