Linux Serial subsystem development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Markus Probst" <markus.probst@posteo.de>
Cc: ojeda@kernel.org, linux-serial@vger.kernel.org
Subject: Re: [PATCH 5/5] rust: serdev: Pause receive callback before calling unbind
Date: Sun, 06 Sep 2026 16:11:32 +0000	[thread overview]
Message-ID: <20260906161132.C5EAA1F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260906-rust_serdev_probe_refactor-v1-5-69cdae0074ec@posteo.de>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Missing memory barrier between setting drvdata and resuming RX allows concurrent NULL pointer dereference.
--

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

rust: serdev: Pause receive callback before calling unbind
    
The receive callback and unbind callback now have exclusive access to
the drivers private data. Provide mutable references in callbacks to
avoid the need for locks in the private data. Remove the Sync
requirement.

> diff --git a/rust/kernel/serdev.rs b/rust/kernel/serdev.rs
> index 66543108ec2fa..7d47d91e3bc35 100644
> --- a/rust/kernel/serdev.rs
> +++ b/rust/kernel/serdev.rs
[ ... ]
> @@ -200,10 +203,14 @@ extern "C" fn receive_buf_callback(
>          // INVARIANT: `sdev` is valid for the duration of `receive_buf_callback()`.
>          let sdev = unsafe { &*sdev.cast::<Device<device::BoundInternal>>() };
>  
> -        // SAFETY: `receive_buf_callback` is only ever called after a successful call to
> -        // `probe_callback`, hence it's guaranteed that `Device::set_drvdata()` has been called
> -        // and stored a `Pin<KBox<PrivateData<'_, T>>>`.
> -        let private_data = unsafe { sdev.as_ref().drvdata_borrow::<PrivateData<'_, T>>() };
> +        // SAFETY:
> +        // - `receive_buf_callback` is only ever called after a successful call to `probe_callback`,
> +        //   hence it's guaranteed that `Device::set_drvdata()` has been called and stored a
> +        //   `Pin<KBox<PrivateData<'_, T>>>`.
> +        // - `unbind_callback` calls `serdev_device_pause_rx` before accessing the driver data,
> +        //   which guarantees that this function will not overlap with it. Thus we have exclusive
> +        //   access.
> +        let private_data = unsafe { sdev.as_ref().drvdata_borrow_mut::<PrivateData<'_, T>>() };

[Severity: Critical]
This is a pre-existing issue, but does this code allow a concurrent NULL pointer
dereference?

In probe_callback() in rust/kernel/serdev.rs, set_drvdata() writes the
driver data pointer to memory, followed by serdev_device_resume_rx() which
clears the SERPORT_PAUSE_RX flag using a relaxed clear_bit() operation:

    unsafe { bindings::serdev_device_resume_rx(sdev.as_raw()) };

On weakly ordered architectures like ARM64, the CPU can reorder the plain data
store to occur after the flag is cleared. A concurrent tty receive path
observing the cleared flag will enter receive_buf_callback() and read
dev->driver_data before the store propagates, obtaining a NULL pointer.

Calling drvdata_borrow_mut() on this NULL pointer creates a reference to NULL,
triggering undefined behavior and a kernel panic. Can this be triggered
externally if the serial port receives data from an attached hardware device
during the narrow window of probe_callback()?

>  
>          T::receive(sdev, private_data.driver_data(), buf)
>      }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260906-rust_serdev_probe_refactor-v1-0-69cdae0074ec@posteo.de?part=5

  reply	other threads:[~2026-09-06 16:11 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-06 15:55 [PATCH 0/5] rust: serdev: Refactor Markus Probst
2026-09-06 15:55 ` [PATCH 1/5] tty: serdev: Export functions to pause receive_buf callback calls Markus Probst
2026-09-06 16:08   ` sashiko-bot
2026-09-06 15:55 ` [PATCH 2/5] rust: serdev: Replace `active` mutex with receive pause Markus Probst
2026-09-06 16:09   ` sashiko-bot
2026-09-06 15:55 ` [PATCH 3/5] rust: serdev: Simplify callbacks Markus Probst
2026-09-06 16:13   ` sashiko-bot
2026-09-06 15:55 ` [PATCH 4/5] rust: Add `Device::drvdata_borrow_mut` Markus Probst
2026-09-06 16:08   ` sashiko-bot
2026-09-06 15:55 ` [PATCH 5/5] rust: serdev: Pause receive callback before calling unbind Markus Probst
2026-09-06 16:11   ` sashiko-bot [this message]
2026-09-06 16:20   ` Danilo Krummrich
2026-09-06 17:36     ` Markus Probst
2026-09-06 20:13     ` Gary Guo
2026-09-06 22:51       ` Markus Probst

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=20260906161132.C5EAA1F00A3A@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-serial@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