From: Yury Norov <yury.norov@gmail.com>
To: Joel Fernandes <joelagnelf@nvidia.com>
Cc: linux-kernel@vger.kernel.org, rust-for-linux@vger.kernel.org,
dri-devel@lists.freedesktop.org, dakr@kernel.org,
acourbot@nvidia.com, Alistair Popple <apopple@nvidia.com>,
Miguel Ojeda <ojeda@kernel.org>,
Alex Gaynor <alex.gaynor@gmail.com>,
Boqun Feng <boqun.feng@gmail.com>, Gary Guo <gary@garyguo.net>,
bjorn3_gh@protonmail.com, Benno Lossin <lossin@kernel.org>,
Andreas Hindborg <a.hindborg@kernel.org>,
Alice Ryhl <aliceryhl@google.com>,
Trevor Gross <tmgross@umich.edu>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
John Hubbard <jhubbard@nvidia.com>, Timur Tabi <ttabi@nvidia.com>,
joel@joelfernandes.org, Elle Rhumsaa <elle@weathered-steel.dev>,
Daniel Almeida <daniel.almeida@collabora.com>,
Andrea Righi <arighi@nvidia.com>,
nouveau@lists.freedesktop.org
Subject: Re: [PATCH v5 8/9] rust: bitfield: Add hardening for out of bounds access
Date: Tue, 30 Sep 2025 14:03:37 -0400 [thread overview]
Message-ID: <aNwbeQ6iXuKIsQHK@yury> (raw)
In-Reply-To: <20250930144537.3559207-9-joelagnelf@nvidia.com>
On Tue, Sep 30, 2025 at 10:45:36AM -0400, Joel Fernandes wrote:
> Similar to bitmap.rs, add hardening to print errors or assert if the
> setter API is used to write out-of-bound values.
>
> Suggested-by: Yury Norov <yury.norov@gmail.com>
> Signed-off-by: Joel Fernandes <joelagnelf@nvidia.com>
> ---
> rust/kernel/bitfield.rs | 32 +++++++++++++++++++++++++++++++-
> security/Kconfig.hardening | 9 +++++++++
> 2 files changed, 40 insertions(+), 1 deletion(-)
>
> diff --git a/rust/kernel/bitfield.rs b/rust/kernel/bitfield.rs
> index a74e6d45ecd3..655f940479f1 100644
> --- a/rust/kernel/bitfield.rs
> +++ b/rust/kernel/bitfield.rs
> @@ -29,6 +29,20 @@ pub const fn into_raw(self) -> T {
> }
> }
>
> +/// Assertion macro for bitfield
> +#[macro_export]
> +macro_rules! bitfield_assert {
> + ($cond:expr, $($arg:tt)+) => {
> + #[cfg(CONFIG_RUST_BITFIELD_HARDENED)]
> + ::core::assert!($cond, $($arg)*);
> +
> + #[cfg(not(CONFIG_RUST_BITFIELD_HARDENED))]
> + if !($cond) {
> + $crate::pr_err!($($arg)+);
> + }
> + }
> +}
Can you discuss performance implication? I'm OK if you decided to make
the check always on, but we need to understand the cost of it.
> /// Bitfield macro definition.
> /// Define a struct with accessors to access bits within an inner unsigned integer.
> ///
> @@ -358,9 +372,25 @@ impl $name {
> $vis fn [<set_ $field>](mut self, value: $to_type) -> Self {
> const MASK: $storage = $name::[<$field:upper _MASK>];
> const SHIFT: u32 = $name::[<$field:upper _SHIFT>];
> + const BITS: u32 = ($hi - $lo + 1) as u32;
> + const MAX_VALUE: $storage =
> + if BITS >= (::core::mem::size_of::<$storage>() * 8) as u32 {
If BITS > storage then it should be a compile time error. Can you
elaborate under which condition this check makes sense, and is not
covered with the "(1<<BITS) - 1" case?
> + !0
> + } else {
> + (1 << BITS) - 1
> + };
> +
> + // Check for overflow - value should fit within the field's bits.
> // Here we are potentially narrowing value from a wider bit value
> // to a narrower bit value. So we have to use `as` instead of `::from()`.
The new comment sounds opposite to the old one: if you check for
overflow, then there's no chance to "potentially narrow the value".
This "potentially" wording simply means undefined behavior.
> - let val = ((value as $storage) << SHIFT) & MASK;
> + let raw_field_value = value as $storage;
> +
> + $crate::bitfield_assert!(
> + raw_field_value <= MAX_VALUE,
> + "value {} exceeds {} for a {} bit field", raw_field_value, MAX_VALUE, BITS
> + );
Can you hide all the internals in the assertion function? Like:
$crate::bitfield_set_assert!(bitfield, field, value, "your message", ...);
We don't need assertion implementation in the main function body.
> +
> + let val = (raw_field_value << SHIFT) & MASK;
> let new_val = (self.raw() & !MASK) | val;
> all the internals in the assertion self.0 = ::kernel::bitfield::BitfieldInternalStorage::from_raw(new_val);
User wants to set an inappropriate value, and you know that because
you just have tested for it. But here you're accepting a definitely
wrong request. This doesn't look right.
On previous rounds you said you can't fail in setter because that
would break the "chain of setters" design. I understand that, but I
think that it's more important to have a clear defensive API that
returns an error when people do wrong things.
So please either find a way to return an error from the setter, or
some other mechanism to abort erroneous request and notify the user.
This "chain of setters" thing looks weird to me as I already said. So
if it messes with a clear API, just drop it.
And to that extend,
a = a.set_field1()
looks more questionable than just
a.set_field1()
because it implies an extra copy. If I do
b = a.set_field1()
would it change the content of 'a'?
Can I do just 'a.set_field1()'? There's no such an example in your
test.
Is that 'a = a.set_field()' thing really a zero-cost comparing to just
'a.set_field()'? Can you ensure it holds, say, on 32-bit machine when
'a' is a 64-bit bitfield? Would it work if we decide to support
bitfields larger than 64-bit, like C does?
Thanks,
Yury
> diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening
> index 86f8768c63d4..e9fc6dcbd6c3 100644
> --- a/security/Kconfig.hardening
> +++ b/security/Kconfig.hardening
> @@ -265,6 +265,15 @@ config RUST_BITMAP_HARDENED
>
> If unsure, say N.
>
> +config RUST_BITFIELD_HARDENED
> + bool "Check integrity of bitfield Rust API"
> + depends on RUST
> + help
> + Enables additional assertions in the Rust Bitfield API to catch
> + values that exceed the bitfield bounds.
> +
> + If unsure, say N.
> +
> config BUG_ON_DATA_CORRUPTION
> bool "Trigger a BUG when data corruption is detected"
> select LIST_HARDENED
> --
> 2.34.1
next prev parent reply other threads:[~2025-09-30 18:03 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-30 14:45 [PATCH v5 0/9] Introduce bitfield and move register macro to rust/kernel/ Joel Fernandes
2025-09-30 14:45 ` [PATCH v5 1/9] nova-core: bitfield: Move bitfield-specific code from register! into new macro Joel Fernandes
2025-09-30 14:45 ` [PATCH v5 2/9] nova-core: bitfield: Add support for different storage widths Joel Fernandes
2025-09-30 17:18 ` Joel Fernandes
2025-10-02 1:17 ` Alexandre Courbot
2025-09-30 14:45 ` [PATCH v5 3/9] nova-core: bitfield: Add support for custom visiblity Joel Fernandes
2025-09-30 14:45 ` [PATCH v5 4/9] rust: Move register and bitfield macros out of Nova Joel Fernandes
2025-09-30 14:45 ` [PATCH v5 5/9] rust: bitfield: Add a new() constructor and raw() accessor Joel Fernandes
2025-09-30 14:45 ` [PATCH v5 6/9] rust: bitfield: Add KUNIT tests for bitfield Joel Fernandes
2025-10-02 1:41 ` Alexandre Courbot
2025-10-02 2:16 ` Elle Rhumsaa
2025-10-02 2:51 ` Alexandre Courbot
2025-10-02 3:35 ` Elle Rhumsaa
2025-10-03 15:23 ` Joel Fernandes
2025-10-04 0:38 ` Alexandre Courbot
2025-10-04 16:14 ` Joel Fernandes
2025-10-06 16:40 ` Miguel Ojeda
2025-10-06 19:50 ` Joel Fernandes
2025-09-30 14:45 ` [PATCH v5 7/9] rust: bitfield: Use 'as' operator for setter type conversion Joel Fernandes
2025-09-30 14:45 ` [PATCH v5 8/9] rust: bitfield: Add hardening for out of bounds access Joel Fernandes
2025-09-30 18:03 ` Yury Norov [this message]
2025-09-30 22:06 ` Joel Fernandes
2025-09-30 14:45 ` [PATCH v5 9/9] rust: bitfield: Add hardening for undefined bits Joel Fernandes
2025-09-30 15:08 ` [PATCH v5 0/9] Introduce bitfield and move register macro to rust/kernel/ Danilo Krummrich
2025-10-02 1:24 ` Alexandre Courbot
2025-10-02 1:26 ` Alexandre Courbot
2025-10-03 15:26 ` Joel Fernandes
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aNwbeQ6iXuKIsQHK@yury \
--to=yury.norov@gmail.com \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=airlied@gmail.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=apopple@nvidia.com \
--cc=arighi@nvidia.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=daniel.almeida@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=elle@weathered-steel.dev \
--cc=gary@garyguo.net \
--cc=jhubbard@nvidia.com \
--cc=joel@joelfernandes.org \
--cc=joelagnelf@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=nouveau@lists.freedesktop.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=simona@ffwll.ch \
--cc=tmgross@umich.edu \
--cc=ttabi@nvidia.com \
--cc=tzimmermann@suse.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).