lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CACQBu=VBvxyNvwSV8_gMuqNv49Ht+7aiUZwHD9Xh-TGoMTQQsw@mail.gmail.com>
Date: Mon, 28 Apr 2025 12:21:38 +0200
From: Burak Emir <bqe@...gle.com>
To: Yury Norov <yury.norov@...il.com>
Cc: Rasmus Villemoes <linux@...musvillemoes.dk>, Viresh Kumar <viresh.kumar@...aro.org>, 
	Miguel Ojeda <ojeda@...nel.org>, Alex Gaynor <alex.gaynor@...il.com>, 
	Boqun Feng <boqun.feng@...il.com>, Gary Guo <gary@...yguo.net>, 
	Björn Roy Baron <bjorn3_gh@...tonmail.com>, 
	Benno Lossin <benno.lossin@...ton.me>, Andreas Hindborg <a.hindborg@...nel.org>, 
	Alice Ryhl <aliceryhl@...gle.com>, Trevor Gross <tmgross@...ch.edu>, rust-for-linux@...r.kernel.org, 
	linux-kernel@...r.kernel.org
Subject: Re: [PATCH v7 3/5] rust: add bitmap API.

On Wed, Apr 23, 2025 at 6:46 PM Yury Norov <yury.norov@...il.com> wrote:
>
> On Wed, Apr 23, 2025 at 01:43:35PM +0000, Burak Emir wrote:
> >
> > Provides an abstraction for C bitmap API and bitops operations.
> > We follow the C Bitmap API closely in naming and semantics, with
> > a few differences that take advantage of Rust language facilities
> > and idioms:
> >
> >   * not all operations are exposed yet, to avoid dead code. This commit
> >     includes enough to implement an Android Binder data structure that
> >     was introduced in commit 15d9da3f818c ("binder: use bitmap for
> >     faster descriptor lookup"), namely drivers/android/dbitmap.h. This
> >     is part of upstreaming the Android Binder driver.
> >
> >   * API uses Option types where appropriate
> >
> >   * bound checks are used to treat out-of-bounds access as bug
> >     (hardening). The C operations treat out-of-bounds parameters
> >     as a default case e.g. "not found" which is safe (avoids UB) but
> >     may hide bugs.
>
> Few paragraphs later you say:
>
> > It enables Rust
> > code to be a lot more similar and predictable with respect to C code
>
> If you want to make Rust similar to C (which is good), you need to
> make all that Panic'ing stuff configurable, right?

Yes, I agree with this reasoning in combination with BUG_ON.

> This is what I suggested originally, and this is the right way to go,
> to me.
>
> There was a long discussion few years ago regarding BUG_ON()s in the
> kernel, and the bottomline for it is simple: the kernel has many nice
> isolating and self-debugging features that help to resolve (hopefully)
> non-fatal errors like out-of-bond access, so we should let it try.

In my own words: using BUG_ON to prevent undefined behavior is almost
always going to be more useful than panic.

> Just halting the kernel helps little, particularly it prevents from
> collecting syslogs and other debugging info. You can check git history
> and see how many BUG()s were demoted to WARN()s, or simply dropped.
>
> So, this is again my suggestion: it's OK to have a hardening feature,
> but the panic should be configurable for the reasons:
>  - robustness;
>  - compatibility;
>  - debugability.
>
> To me, this should end up with something like:
>
>   fn bitmap_assert(bool, msg)
>   {
>   #if CONFIG_RUST_HARDENING_PANIC && CONFIG_RUST_BITMAP_HARDENING
>         assert(bool, msg)
>   #elif CONFIG_RUST_BITMAP_HARDENING
>         if (!bool)
>                 pr_err(msg)
>   #else
>         // do nothing; for the best performance.
>   #endif
>   }
>
> This doesn't look difficult anyhow right? But if you find it
> impractical, you can just replace the panic with printing an error.

There are several things at play:
- for the C methods that tolerate out-of-bounds access, the
bounds-check is redundant for safety
- but it is not redundant in terms of API: tolerating out-of-bounds
access is the spec, someone may rely on it
- if we would like a Rust API that is stricter (hardening), it is an
API change (or: a Rust and C API difference).

I will go with your suggestion and do a local (bitmap-specific)
configurable assert (=panic).
This could then later be changed to use a BUG macro.

> After all, this # Panic simply breaks your own coding rules:
>
>   Please note that panicking should be very rare and used only with a good
>   reason. In almost all cases, a fallible approach should be used, typically
>   returning a ``Result``.
>

Bitmap operations are so basic and the API that fallibility does not
make sense to me here.
The Rust API is also constrained by what the C API provides: if C
handles out-of-bounds arguments gracefully, then Rust should, too.
And panicking has the problems you described, so I have come around to
think that Rust needs a BUG_ON macro.

> >   * better naming convention to distinguish non-atomic from atomic
> >     operations: {set,clear}_bit vs {set,clear}_bit_atomic.
> >     The Rust type system ensures that all non-atomic operations
> >     require a &mut reference which amounts to exclusive access.
> >     Using the atomic variants only makes sense when multiple threads
> >     have a shared reference &bitmap which amounts to the interior
> >     mutability pattern.
> >
> >   * optimized to represent the bitmap inline if it would take the space
> >     of a pointer. This saves allocations which is relevant in the
> >     Binder use case.
> >
> > The underlying C bitmap is *not* exposed. This would lose all static
> > guarantees.
> >
> > An alternative route of vendoring an existing Rust bitmap package was
> > considered but suboptimal overall. Reusing the C implementation is
> > preferable for a basic data structure like bitmaps. It enables Rust
> > code to be a lot more similar and predictable with respect to C code
> > that uses the same data structures and enables the use of code that
> > has been tried-and-tested in the kernel.
> >
> > We use the `usize` type for sizes and indices into the bitmap,
> > because Rust generally always uses that type for indices and lengths
> > and it will be more convenient if the API accepts that type. This means
> > that we need to perform some casts to/from u32 and usize, since the C
> > headers use unsigned int instead of size_t/unsigned long for these
> > numbers in some places.
> >
> > Adds new MAINTAINERS section BITMAP API [RUST].
> >
> > Suggested-by: Alice Ryhl <aliceryhl@...gle.com>
> > Suggested-by: Yury Norov <yury.norov@...il.com>
> > Signed-off-by: Burak Emir <bqe@...gle.com>
> > ---
> >  MAINTAINERS           |   7 +
> >  rust/kernel/bitmap.rs | 396 ++++++++++++++++++++++++++++++++++++++++++
> >  rust/kernel/lib.rs    |   1 +
> >  3 files changed, 404 insertions(+)
> >  create mode 100644 rust/kernel/bitmap.rs
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index 1f162f64eded..7d107dc91390 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -4135,6 +4135,13 @@ S:     Maintained
> >  F:   rust/helpers/bitmap.c
> >  F:   rust/helpers/cpumask.c
> >
> > +BITMAP API [RUST]
> > +M:   Alice Ryhl <aliceryhl@...gle.com>
> > +M:   Burak Emir <bqe@...gle.com>
> > +R:   Yury Norov <yury.norov@...il.com>
> > +S:   Maintained
> > +F:   rust/kernel/bitmap.rs
> > +
> >  BITOPS API
> >  M:   Yury Norov <yury.norov@...il.com>
> >  R:   Rasmus Villemoes <linux@...musvillemoes.dk>
> > diff --git a/rust/kernel/bitmap.rs b/rust/kernel/bitmap.rs
> > new file mode 100644
> > index 000000000000..79ddbef2b028
> > --- /dev/null
> > +++ b/rust/kernel/bitmap.rs
> > @@ -0,0 +1,396 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +
> > +// Copyright (C) 2025 Google LLC.
> > +
> > +//! Rust API for bitmap.
> > +//!
> > +//! C headers: [`include/linux/bitmap.h`](srctree/include/linux/bitmap.h).
> > +
> > +use crate::alloc::{AllocError, Flags};
> > +use crate::bindings;
> > +use core::ptr::NonNull;
> > +
> > +/// Holds either a pointer to array of `unsigned long` or a small bitmap.
> > +#[repr(C)]
> > +union BitmapRepr {
> > +    bitmap: usize,
> > +    ptr: NonNull<usize>,
> > +}
> > +
> > +    pub fn last_bit(&self) -> Option<usize> {
>
> [...]
>
> > +        // SAFETY: access is within bounds.
> > +        let index = unsafe { bindings::_find_last_bit(self.as_ptr(), self.nbits) };
> > +        if index == self.nbits {
>
> Here and everywhere, can you please:
>
>         if index >= self.nbits {
>
> I know that bitmap documentation says that index would be exactly
> nbits, but really it was a bad decision. If one day I'll find a safe
> way to relax this to >=, your code will stay untouched.

Done, going to be in v8.

Thanks,
Burak

>
> Thanks,
> Yury

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ