Linux CAN drivers development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Fan Wu" <fanwu01@zju.edu.cn>
Cc: linux-can@vger.kernel.org,
	"Oliver Hartkopp" <socketcan@hartkopp.net>,
	"Marc Kleine-Budde" <mkl@pengutronix.de>,
	"Oleksij Rempel" <o.rempel@pengutronix.de>,
	"Vincent Mailhol" <mailhol@kernel.org>
Subject: Re: [PATCH net] can: esd_usb: kill anchored URBs before freeing netdevs
Date: Fri, 10 Jul 2026 10:47:26 +0000	[thread overview]
Message-ID: <20260710104726.EAD691F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260709104620.133765-1-fanwu01@zju.edu.cn>

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

Pre-existing issues:
- [High] Malicious USB devices or normal operations can trigger a NULL pointer dereference if `esd_usb_probe_one_net()` fails for a network interface.
- [High] A zero-length message from the USB device causes an infinite loop in the RX completion handler, leading to a softirq CPU lockup.
- [High] The driver parses and copies USB message payload into CAN frames before validating that the message length fits within the received USB data or allocated buffer.
- [High] Double-free and Use-After-Free of echo_skb during device teardown due to missing URB cancellation in `ndo_stop`.
- [Medium] If `usb_submit_urb()` fails in `esd_usb_start_xmit()`, the allocated TX context is never released, leading to a permanent depletion of TX contexts.
--

--- Patch [1]: [PATCH net] can: esd_usb: kill anchored URBs before freeing netdevs ---
commit f2616c0b84f4389121d1ebf004051cb8242711c9
Author: Fan Wu <fanwu01@zju.edu.cn>

can: esd_usb: kill anchored URBs before freeing netdevs

This commit reorders the teardown sequence in esd_usb_disconnect so that
anchored URBs are killed before the CAN netdevs are freed. This prevents a
use-after-free where unlink_all_urbs would otherwise dereference a
previously freed network device structure to cancel active TX jobs.

> diff --git a/drivers/net/can/usb/esd_usb.c b/drivers/net/can/usb/esd_usb.c
> index d257440fa01ff..f41d4a0d140f7 100644
> --- a/drivers/net/can/usb/esd_usb.c
> +++ b/drivers/net/can/usb/esd_usb.c
> @@ -1390,10 +1390,13 @@ static void esd_usb_disconnect(struct usb_interface *intf)
>  				netdev = dev->nets[i]->netdev;
>  				netdev_info(netdev, "unregister\n");
>  				unregister_netdev(netdev);
> -				free_candev(netdev);
>  			}
>  		}
>  		unlink_all_urbs(dev);
> +		for (i = 0; i < dev->net_count; i++) {
> +			if (dev->nets[i])
> +				free_candev(dev->nets[i]->netdev);
> +		}
>  		kfree(dev);
>  	}
>  }

[Severity: High]
This isn't a bug introduced by this patch, but if esd_usb_probe_one_net
fails during initialization, could it lead to a NULL pointer dereference
later?

In esd_usb_probe:
	for (i = 0; i < dev->net_count; i++)
		esd_usb_probe_one_net(intf, i);

If the probe fails for a specific network interface, dev->nets[i] remains
NULL because the error is ignored. If a USB device sends a message for that
uninitialized network index, is it safe to pass it directly to
esd_usb_rx_can_msg?

In esd_usb_read_bulk_callback:
		case ESD_USB_CMD_CAN_RX:
			if (msg->rx.net >= dev->net_count) {
				dev_err(dev->udev->dev.parent, "format error\n");
				break;
			}

			esd_usb_rx_can_msg(dev->nets[msg->rx.net], msg);

[Severity: High]
This is a pre-existing issue, but does a zero-length message from the USB
device cause an infinite loop in the RX completion handler?

In esd_usb_read_bulk_callback:
		pos += msg->hdr.len * sizeof(u32); /* convert to # of bytes */

		if (pos > urb->actual_length) {
			dev_err(dev->udev->dev.parent, "format error\n");
			break;
		}

If a local USB device sets msg->hdr.len = 0, pos will not advance,
potentially causing the loop condition pos < urb->actual_length to run
infinitely and lock up the CPU in softirq context.

[Severity: High]
This is a pre-existing issue, but does the driver parse the USB message
payload before ensuring it fits within the received buffer?

In esd_usb_read_bulk_callback:
	while (pos < urb->actual_length) {
		union esd_usb_msg *msg;

		msg = (union esd_usb_msg *)(urb->transfer_buffer + pos);

		switch (msg->hdr.cmd) {
		case ESD_USB_CMD_CAN_RX:
// ...
			esd_usb_rx_can_msg(dev->nets[msg->rx.net], msg);

The message fields seem to be parsed and passed to handlers like
esd_usb_rx_can_msg which read from the buffer, but the boundary check
evaluating pos > urb->actual_length happens at the end of the loop. Can this
lead to an out-of-bounds read if a message is positioned near the end of the
transfer buffer?

[Severity: High]
This is a pre-existing issue, but is there a potential double-free of
echo_skb during device teardown?

In esd_usb_close:
	priv->can.state = CAN_STATE_STOPPED;

	netif_stop_queue(netdev);

	close_candev(netdev);

	return err;

Since close_candev flushes the echo_skb array without locking, and
esd_usb_close does not appear to kill active URBs before this point, could
a concurrent TX URB completion fire in softirq?

In esd_usb_tx_done_msg:
		stats->tx_errors++;
		can_free_echo_skb(netdev, context->echo_index, NULL);

If both paths access and free the exact same echo_skb concurrently, this
might lead to memory corruption.

[Severity: Medium]
This is a pre-existing issue, but if usb_submit_urb fails in
esd_usb_start_xmit, does it permanently leak a TX context?

In esd_usb_start_xmit:
	err = usb_submit_urb(urb, GFP_ATOMIC);
	if (err) {
		can_free_echo_skb(netdev, context->echo_index, NULL);

		atomic_dec(&priv->active_tx_jobs);
		usb_unanchor_urb(urb);

The error path frees the echo_skb, but it appears to miss resetting
context->echo_index back to ESD_USB_MAX_TX_URBS. If this happens repeatedly
due to transient errors, could it permanently exhaust all 16 contexts and
stall network transmission?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260709104620.133765-1-fanwu01@zju.edu.cn?part=1

      parent reply	other threads:[~2026-07-10 10:47 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-09 10:46 [PATCH net] can: esd_usb: kill anchored URBs before freeing netdevs Fan Wu
2026-07-09 15:17 ` Jagielski, Jedrzej
2026-07-09 16:41 ` [PATCH net v2] " Fan Wu
2026-07-10 16:43   ` sashiko-bot
2026-07-10 10:47 ` 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=20260710104726.EAD691F000E9@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=fanwu01@zju.edu.cn \
    --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