Linux CAN drivers development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Oliver Hartkopp" <socketcan@hartkopp.net>
Cc: "Oleksij Rempel" <o.rempel@pengutronix.de>,
	"Marc Kleine-Budde" <mkl@pengutronix.de>,
	linux-can@vger.kernel.org, "Vincent Mailhol" <mailhol@kernel.org>,
	"Oliver Hartkopp" <socketcan@hartkopp.net>
Subject: Re: [PATCH] can: isotp: add missing synchronize_rcu() in isotp_notify()
Date: Tue, 07 Jul 2026 08:52:10 +0000	[thread overview]
Message-ID: <20260707085210.6B6C01F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260707083228.47629-1-socketcan@hartkopp.net>

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

New issues:
- [High] System-wide RTNL lock stall and DoS due to O(N) sequential synchronize_rcu() calls in a netdevice notifier.

Pre-existing issues:
- [High] Race condition in isotp_release() and bcm_release() during concurrent device unregistration leads to skipped filter unregistration, leaking receiver entries and causing UAF on CAN frame reception.
--

--- Patch [1]: [PATCH] can: isotp: add missing synchronize_rcu() in isotp_notify() ---
commit e2052e358a8bcbb3b1bce1aa1280f280d7e67f64
Author: Oliver Hartkopp <socketcan@hartkopp.net>

can: isotp: add missing synchronize_rcu() in isotp_notify()

isotp_notify() unregisters the CAN filters without waiting for an RCU grace
period. This commit adds a synchronize_rcu() to wait for in-flight isotp_rcv()
callers to finish before clearing so->bound. This prevents a use-after-free
timer callback on a freed socket if isotp_release() skips its own
synchronize_rcu() when NETDEV_UNREGISTER runs first.

> diff --git a/net/can/isotp.c b/net/can/isotp.c
> index c48b4a818297e..008cee5472130 100644
> --- a/net/can/isotp.c
> +++ b/net/can/isotp.c
> @@ -1575,6 +1575,13 @@ static void isotp_notify(struct isotp_sock *so, unsigned long msg,
>  			can_rx_unregister(dev_net(dev), dev, so->txid,
>  					  SINGLE_MASK(so->txid),
>  					  isotp_rcv_echo, sk);
> +
> +			/* wait for in-flight isotp_rcv() callers to finish
> +			 * before clearing so->bound, so that isotp_release()
> +			 * cannot observe so->bound == 0 and skip its own
> +			 * synchronize_rcu() while a callback is still running
> +			 */
> +			synchronize_rcu();

[Severity: High]
Does this regression introduce an O(N) synchronize_rcu() stall under the
rtnl_lock?

Looking at isotp_notifier(), it loops over all sockets and calls isotp_notify():

net/can/isotp.c:isotp_notifier() {
    list_for_each_entry(isotp_busy_notifier, &isotp_notifier_list, notifier) {
        spin_unlock(&isotp_notifier_lock);
        isotp_notify(isotp_busy_notifier, msg, dev);
        ...
}

Because netdevice notifiers are invoked with the rtnl_lock held, iterating over
thousands of sockets bound to the interface will trigger sequential RCU grace
periods. Can this stall the rtnl_lock for minutes and freeze network
configuration tasks?


[Severity: High]
This is a pre-existing issue, but does a race condition in isotp_release()
also lead to skipped filter unregistration and a use-after-free?

If a socket is closed exactly while the device it is bound to is being
unregistered, dev_get_by_index() can return NULL because unlist_netdevice()
is called before the NETDEV_UNREGISTER notifier fires:

net/core/dev.c:unregister_netdevice_many_notify() {
    ...
    unlist_netdevice(dev);
    ...
    synchronize_net();
    ...
    call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
    ...
}

If isotp_release() executes in this window, it removes the socket from
isotp_notifier_list, then calls dev_get_by_index() which returns NULL:

net/can/isotp.c:isotp_release() {
    ...
    dev = dev_get_by_index(net, so->ifindex);
    if (dev) {
    ...
}

As a result, isotp_release() completely skips filter unregistration and the
synchronize_rcu() call. The notifier will subsequently skip this socket
because it is no longer in the list. The CAN receive filter remains active
and points to the socket which is then freed.

Could this cause a use-after-free if an isotp_rcv() callback is currently
in-flight or triggered by pending loopback frames? The same logic flaw
appears to exist in bcm_release().

>  		}
>  
>  		so->ifindex = 0;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260707083228.47629-1-socketcan@hartkopp.net?part=1

      reply	other threads:[~2026-07-07  8:52 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-07  8:32 [PATCH] can: isotp: add missing synchronize_rcu() in isotp_notify() Oliver Hartkopp
2026-07-07  8:52 ` 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=20260707085210.6B6C01F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=linux-can@vger.kernel.org \
    --cc=mailhol@kernel.org \
    --cc=mkl@pengutronix.de \
    --cc=o.rempel@pengutronix.de \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=socketcan@hartkopp.net \
    /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