All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: hyunjungg <hj351016@gmail.com>, linux-can@vger.kernel.org
Cc: "Marc Kleine-Budde" <mkl@pengutronix.de>,
	"Oliver Hartkopp" <socketcan@hartkopp.net>,
	"Vincent Mailhol" <mailhol@kernel.org>,
	"Oleksij Rempel" <o.rempel@pengutronix.de>
Subject: Re: [PATCH] can: peak_usb: pcan_usb: cancel restart timer on stop to avoid use-after-free
Date: Sun, 08 Nov 2026 15:33:36 +0000	[thread overview]
Message-ID: <sashiko-outbox-203833@kernel.org> (raw)
In-Reply-To: <20261107153319.3765325-1-hj351016@gmail.com>

Thank you for your contribution! Sashiko AI review found 1 potential
issue to consider:
- [Medium] can: peak_usb: in-flight restart URB arms timer after
  pcan_usb_stop()
It also noticed 1 related pre-existing issue this patch does not
introduce:
- [Critical] can: peak_usb: incomplete restart_timer cleanup in
  peak_usb_create_dev() [1]
--

commit 711582c698eedc1cd7434111f52222eb7dcd4279
Author: Hyunjung Ko <hj351016@gmail.com>

can: peak_usb: pcan_usb: cancel restart timer on stop to avoid use-after-free

This commit adds a dev_stop callback to pcan_usb that calls
timer_delete_sync() on pdev->restart_timer when the interface is stopped.

> diff --git a/drivers/net/can/usb/peak_usb/pcan_usb.c b/drivers/net/can/usb/peak_usb/pcan_usb.c
> index 8fd058c328564..4c131958b5aa6 100644
> --- a/drivers/net/can/usb/peak_usb/pcan_usb.c
> +++ b/drivers/net/can/usb/peak_usb/pcan_usb.c
> @@ -882,6 +882,14 @@ static int pcan_usb_start(struct peak_usb_device *dev)
>  	return pcan_usb_set_ext_vcc(dev, 0);
>  }
>  
> +static int pcan_usb_stop(struct peak_usb_device *dev)
> +{
> +	struct pcan_usb *pdev = container_of(dev, struct pcan_usb, dev);
> +
> +	timer_delete_sync(&pdev->restart_timer);
> +	return 0;
> +}

[Severity: Medium]
Can an in-flight restart URB complete after pcan_usb_stop() and re-arm
pdev->restart_timer?

pcan_usb_restart_async() submits its bulk URB without anchoring it to
dev->tx_submitted, so peak_usb_unlink_all_urbs() does not kill it before
calling dev_stop().  In addition, pcan_usb_restart_pending() unconditionally
calls mod_timer(&pdev->restart_timer, ...) without checking urb->status or
PCAN_USB_STATE_STARTED:

CPU0                              CPU1
can_restart()
  ...
    pcan_usb_restart_async()
      usb_submit_urb(urb, ...)
peak_usb_ndo_stop()
  peak_usb_unlink_all_urbs(dev)
  pcan_usb_stop(dev)
    timer_delete_sync(&pdev->restart_timer)
                                  pcan_usb_restart_pending(urb)
                                    mod_timer(&pdev->restart_timer, ...)
  ...
  free_candev(netdev)
                                  pcan_usb_restart()
                                    peak_usb_restart_complete(&pdev->dev)
                                      <-- use-after-free

If the interface remains registered, pcan_usb_restart() marks a stopped
interface as CAN_STATE_ERROR_ACTIVE and wakes its queue; if the USB device
disconnects after peak_usb_ndo_stop() has cleared IFF_UP, unregister_candev()
does not call peak_usb_ndo_stop() again and free_candev() frees pdev while
restart_timer is still armed.

Anchoring the restart URB so peak_usb_unlink_all_urbs() kills it before
pcan_usb_stop(), or only arming restart_timer in pcan_usb_restart_pending()
when urb->status == 0 and PCAN_USB_STATE_STARTED is set, would close this
race.

> +
>  static int pcan_usb_init(struct peak_usb_device *dev)
>  {
>  	struct pcan_usb *pdev = container_of(dev, struct pcan_usb, dev);

[Severity: Critical]
This problem wasn't introduced by this patch, but can a failed probe in
peak_usb_create_dev() free netdev while pdev->restart_timer is still armed
[1]?

peak_usb_create_dev() calls register_candev(netdev) before calling
dev->adapter->dev_init() (pcan_usb_init()) and dev->adapter->dev_set_bus():

drivers/net/can/usb/peak_usb/pcan_usb_core.c:peak_usb_create_dev() {
	...
	err = register_candev(netdev);
	if (err) {
		...
		goto lbl_restore_intf_data;
	}
	...
	if (dev->adapter->dev_init) {
		err = dev->adapter->dev_init(dev);
		if (err)
			goto lbl_unregister_candev;
	}

	/* set bus off */
	if (dev->adapter->dev_set_bus) {
		err = dev->adapter->dev_set_bus(dev, 0);
		if (err)
			goto adap_dev_free;
	}
	...
adap_dev_free:
	if (dev->adapter->dev_free)
		dev->adapter->dev_free(dev);

lbl_unregister_candev:
	unregister_candev(netdev);
	...
lbl_free_candev:
	free_candev(netdev);
}

Because register_candev() publishes the netdev and drops rtnl_lock before
pcan_usb_init() or dev_set_bus() blocks on USB bulk transfers, another
context can open the device and trigger a bus-off restart via
pcan_usb_restart_async().  If pcan_usb_get_serial() fails in pcan_usb_init(),
or if an in-flight restart URB completes after unregister_candev(),
free_candev() frees pdev while restart_timer is pending, causing a
use-after-free when pcan_usb_restart() fires.

[1] https://sashiko.dev/#/bug/linux-c6d07ad0-7ac4-41cf-a567-927ba96a5e93

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261107153319.3765325-1-hj351016@gmail.com?part=1

  reply	other threads:[~2026-11-08 15:33 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-07 15:33 [PATCH] can: peak_usb: pcan_usb: cancel restart timer on stop to avoid use-after-free hyunjungg
2026-11-08 15:33 ` sashiko-bot [this message]
2026-11-09  4:24 ` netdev-bot+sashiko
2026-11-09  4:49   ` khj

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=sashiko-outbox-203833@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=hj351016@gmail.com \
    --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 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.