All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Markus Probst" <markus.probst@posteo.de>
Cc: ojeda@kernel.org, linux-pci@vger.kernel.org
Subject: Re: [PATCH v18 3/3] rust: leds: add multicolor classdev abstractions
Date: Sat, 30 May 2026 23:25:45 +0000	[thread overview]
Message-ID: <20260530232546.53ED31F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260531-rust_leds-v18-3-d07102ba5170@posteo.de>

Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:
- [High] Data race and Undefined Behavior due to `&[MultiColorSubLed]` exposing concurrently mutated plain `u32` fields.
- [High] Reconstructing KVec with a hardcoded capacity violates the `KVec::from_raw_parts` safety contract.
- [High] FwNode reference count leak or Use-After-Free when `name` is explicitly set.
- [Low] Dead documentation link for `MultiColorSubLed::brightness`.
- [Low] Missing `#[inline]` attribute on the `from_raw` internal helper function.
--

commit 06862c24665d65b7a33c6a01c9dd3881267810e1
Author: Markus Probst <markus.probst@posteo.de>

rust: leds: add multicolor classdev abstractions
    
Implement the abstractions needed for multicolor led class devices,
including `led::MultiColor` and `MultiColorDevice`.

> diff --git a/rust/kernel/led/multicolor.rs b/rust/kernel/led/multicolor.rs
> new file mode 100644
> index 0000000000000..18c9d36221f1e
> --- /dev/null
> +++ b/rust/kernel/led/multicolor.rs

[ ... ]

> +#[repr(C)]
> +#[derive(Copy, Clone, Debug)]
> +#[non_exhaustive]
> +pub struct MultiColorSubLed {
> +    /// the color of the sub led
> +    pub color: Color,
> +    /// the brightness of the sub led.
> +    ///
> +    /// The value will be automatically calculated.
> +    /// See `MultiColor::pre_brightness_set`.

[Severity: Low]
Is the reference to MultiColor::pre_brightness_set correct?  This function
does not appear to exist in the code, and MultiColor is a marker enum.

> +    pub brightness: u32,
> +    /// the intensity of the sub led.
> +    pub intensity: u32,
> +    /// arbitrary data for the driver to store.
> +    pub channel: u32,
> +}

[Severity: High]
Does this expose concurrently mutated fields as plain integers?

When the C kernel LED core modifies the subled values (for instance, via
led_mc_calc_color_components modifying brightness during sysfs writes),
these fields are mutated without Rust-visible synchronization.

Since MultiColorDevice::subleds() hands out a shared, immutable slice
&[MultiColorSubLed] to the driver, does using plain u32 instead of
interior mutability primitives like Opaque or UnsafeCell violate strict
aliasing invariants and risk undefined behavior?

[ ... ]

> +                let subled_guard = ScopeGuard::new(|| {
> +                    // SAFETY: `subled_info` is guaranteed to be a valid array pointer to
> +                    // `mc_subled` with the length and capacity of `num_colors`.
> +                    drop(unsafe { KVec::from_raw_parts(subled_info, num_colors, num_colors) });
> +                });

[Severity: High]
Is it safe to hardcode the capacity to num_colors when reconstructing
this KVec?

The original KVec was dynamically allocated using extend_from_slice(subleds)
which could potentially over-allocate.  Since the exact allocated capacity 
is verified but then discarded, reconstructing the KVec here (and during 
PinnedDrop) with num_colors as the capacity might violate 
KVec::from_raw_parts safety contract.

Should the exact capacity be stored, or perhaps a boxed slice (KBox<[T]>)
used instead to ensure the allocator frees the correct size?

[ ... ]

> +                // SAFETY:
> +                // - `parent.as_ref().as_raw()` is guaranteed to be a pointer to a valid
> +                //    `device`.
> +                // - `ptr` is guaranteed to be a pointer to an initialized `led_classdev_mc`.
> +                to_result(unsafe {
> +                    bindings::led_classdev_multicolor_register_ext(
> +                        parent.as_ref().as_raw(),
> +                        ptr,
> +                        if self.name.is_none() {
> +                            &raw mut init_data
> +                        } else {
> +                            core::ptr::null_mut()
> +                        },
> +                    )
> +                })?;
> +
> +                subled_guard.dismiss();
> +
> +                core::mem::forget(self.fwnode); // keep the reference count incremented

[Severity: High]
Could this lead to a fwnode reference count leak or a use-after-free if
self.name is configured?

If self.name is set, a null pointer is passed to register the device instead
of &mut init_data, meaning the C device does not inherit the provided fwnode.
However, self.fwnode is unconditionally forgotten, which leaves its reference
count incremented.

Later, during device drop, dev.fwnode() is queried to decrement the refcount.
If the device has no fwnode, it returns None, permanently leaking the original
fwnode. If the device inherited a fwnode from its parent, dev.fwnode() would
return the parent's fwnode, incorrectly decrementing it and potentially causing
a use-after-free of the parent's fwnode.

[ ... ]

> +impl<'bound, T: LedOps<Mode = MultiColor> + 'bound> MultiColorDevice<'bound, T> {
> +    /// # Safety
> +    /// `led_cdev` must be a valid pointer to a `led_classdev` embedded within a
> +    /// `led::MultiColorDevice`.
> +    unsafe fn from_raw<'a>(led_cdev: *mut bindings::led_classdev) -> &'a Self {

[Severity: Low]
this isn't a bug, but should this internal helper function have an #[inline]
attribute?

According to the Rust subsystem guidelines, small internal helper functions
within abstractions should be annotated with #[inline]. Since this method
consists exclusively of unsafe pointer arithmetic (container_of!), it seems
it should be inlined.

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260531-rust_leds-v18-0-d07102ba5170@posteo.de?part=3

  reply	other threads:[~2026-05-30 23:25 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-30 22:49 [PATCH v18 0/3] rust: leds: add led classdev abstractions Markus Probst
2026-05-30 22:49 ` [PATCH v18 1/3] rust: leds: add basic " Markus Probst
2026-05-30 23:05   ` sashiko-bot
2026-05-30 23:48     ` Markus Probst
2026-05-30 22:49 ` [PATCH v18 2/3] rust: leds: add Mode trait Markus Probst
2026-05-30 23:17   ` sashiko-bot
2026-05-30 23:51     ` Markus Probst
2026-05-30 22:49 ` [PATCH v18 3/3] rust: leds: add multicolor classdev abstractions Markus Probst
2026-05-30 23:25   ` sashiko-bot [this message]
2026-05-31  0:36     ` Markus Probst
2026-05-31  7:55   ` Onur Özkan

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=20260530232546.53ED31F00893@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=markus.probst@posteo.de \
    --cc=ojeda@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.