Linux PCI subsystem development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Markus Probst" <markus.probst@posteo.de>
Cc: linux-pci@vger.kernel.org, linux-leds@vger.kernel.org,
	lee@kernel.org, ojeda@kernel.org
Subject: Re: [PATCH v21 3/3] rust: leds: add multicolor classdev abstractions
Date: Mon, 29 Jun 2026 13:55:29 +0000	[thread overview]
Message-ID: <20260629135530.4E4FE1F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260629-rust_leds-v21-3-4f0f19579db5@posteo.de>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Unsynchronized reads of concurrently modified `intensity` and `brightness` fields in `MultiColorSubLed` cause a data race and Undefined Behavior in safe Rust.
- [High] Flawed `fwnode` reference counting ownership in `MultiColorDevice` leads to potential Use-After-Free or memory leak.
--

commit 53cb84fc2ecc8ded772da6376e83ccc60f89c50f
Author: Markus Probst <markus.probst@posteo.de>

rust: leds: add multicolor classdev abstractions

Implement the abstractions needed for multicolor led class devices.

> diff --git a/rust/kernel/led/multicolor.rs b/rust/kernel/led/multicolor.rs
> new file mode 100644
> index 0000000000000..2c55140dd37ed
> --- /dev/null
> +++ b/rust/kernel/led/multicolor.rs
> @@ -0,0 +1,460 @@
[ ... ]
> +    /// The intensity of the sub led.
> +    #[inline]
> +    pub const fn intensity(&self) -> u32 {
> +        // SAFETY:
> +        // - `self.intensity.get()` is a valid pointer to `u32`.
> +        // - We don't have exclusive or immutable access to `self.intensity`,
> +        //   but the alignment should prevent "load tearing".
> +        unsafe { *self.intensity.get() }

[Severity: High]
Does this unsynchronized raw pointer read risk causing a data race and
Undefined Behavior in safe Rust?

The C multicolor LED core modifies subled_info[i].intensity and brightness
concurrently when a user writes to sysfs attributes. Meanwhile, this safe Rust
getter method performs an unsynchronized raw pointer read. Since
MultiColorDevice implements Sync, multiple threads can share
MultiColorSubLed and read these fields at any time.

Should this use core::ptr::read_volatile to ensure soundness?

> +    }
> +
> +    /// The brightness of the sub led.
> +    #[inline]
> +    pub const fn brightness(&self) -> u32 {
> +        // SAFETY:
> +        // - `self.brightness.get()` is a valid pointer to `u32`.
> +        // - We don't have exclusive or immutable access to `self.brightness`,
> +        //   but the alignment should prevent "load tearing".
> +        unsafe { *self.brightness.get() }

[Severity: High]
Similarly, does this unsynchronized read of brightness risk causing a data
race when the C side modifies it concurrently?

Should core::ptr::read_volatile be used here as well?

[ ... ]
> +                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]
Does leaking the fwnode reference count to the C subsystem and then trying
to reclaim it in drop() by reading dev.fwnode() risk a Use-After-Free?

If the kernel (e.g. ACPI) assigns a different fwnode to the device after
registration, dev.fwnode() will return this new fwnode. The drop()
implementation below would then incorrectly take ownership of the new
fwnode's reference count and drop it, while permanently leaking the
originally passed fwnode.

Should MultiColorDevice store Option<ARef<FwNode>> locally to ensure it
only manages the exact reference it uniquely owns?

> +
> +                Ok::<_, Error>(())
> +            }),
> +            _p: PhantomData,
> +        })
[ ... ]
> +#[pinned_drop]
> +impl<'bound, T: LedOps<Mode = MultiColor> + 'bound> PinnedDrop for MultiColorDevice<'bound, T> {
> +    fn drop(self: Pin<&mut Self>) {
> +        let raw = self.classdev.get();
> +        // SAFETY: The existence of `self` guarantees that `self.classdev.get()` is a pointer to a
> +        // valid `led_classdev_mc`.
> +        let dev: &device::Device = unsafe { device::Device::from_raw((*raw).led_cdev.dev) };
> +
> +        let _fwnode = dev
> +            .fwnode()
> +            // SAFETY: the reference count of `fwnode` has previously been
> +            // incremented in `led::DeviceBuilder::build_multicolor`.
> +            .map(|fwnode| unsafe { ARef::from_raw(NonNull::from(fwnode)) });

[Severity: High]
Is it safe to unconditionally reconstruct an ARef from dev.fwnode() here?

As mentioned above, if dev.fwnode() returns a different fwnode than the one
originally passed to build_multicolor, this will drop a reference it does not
own, potentially leading to a Use-After-Free, while the originally leaked
reference remains un-dropped.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260629-rust_leds-v21-0-4f0f19579db5@posteo.de?part=3

      reply	other threads:[~2026-06-29 13:55 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-29 13:10 [PATCH v21 0/3] rust: leds: add led classdev abstractions Markus Probst
2026-06-29 13:10 ` [PATCH v21 1/3] rust: leds: add basic " Markus Probst
2026-06-29 13:36   ` sashiko-bot
2026-06-29 13:10 ` [PATCH v21 2/3] rust: leds: add Mode trait Markus Probst
2026-06-29 13:40   ` sashiko-bot
2026-06-29 13:10 ` [PATCH v21 3/3] rust: leds: add multicolor classdev abstractions Markus Probst
2026-06-29 13:55   ` sashiko-bot [this message]

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=20260629135530.4E4FE1F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=lee@kernel.org \
    --cc=linux-leds@vger.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox