From: netdev-bot+sashiko@kernel.org
To: mkl@pengutronix.de
Cc: netdev@vger.kernel.org, davem@davemloft.net, kuba@kernel.org,
linux-can@vger.kernel.org, kernel@pengutronix.de,
socketcan@hartkopp.net, kurt.van.dijck@eia.be
Subject: Re: [PATCH net-next 28/37] can: ems_usb: use usb_kill_urb() to stop the intr URB
Date: Fri, 16 Oct 2026 02:37:14 +0000 [thread overview]
Message-ID: <179211823441.434549.9677243526506061190@kernel.org> (raw)
In-Reply-To: <20261015015336.816543-29-mkl@pengutronix.de>
Thank you for your contribution! Sashiko AI review found more severe
issue(s) in other patches of this series. This mail is only an FYI, in case
you want to address the nit picks below when you respin.
Low priority / nit picks for your consideration:
- [Low] Now that unlink_all_urbs() stops the intr URB with
usb_kill_urb(), there is a new race window on close.
Pre-existing issues:
- [Critical] unlink_all_urbs() in drivers/net/can/usb/ems_usb.c (lines
755-757) can free the RX coherent buffers twice.
- [Medium] ems_usb_start() does not undo partial setup when it fails.
--
can: ems_usb: use usb_kill_urb() to stop the intr URB
This commit changes unlink_all_urbs() to stop the intr URB with
usb_kill_urb() instead of usb_unlink_urb(). The goal is to make sure
ems_usb_read_interrupt_callback() has returned before
ems_usb_disconnect() frees dev->intr_in_buffer and the candev.
Link: https://patch.msgid.link/20260923030522.409344-1-fanwu01@zju.edu.cn
> diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
> index 24cf8f651f8f..2d31f0b86859 100644
> --- a/drivers/net/can/usb/ems_usb.c
> +++ b/drivers/net/can/usb/ems_usb.c
> @@ -748,7 +748,7 @@ static void unlink_all_urbs(struct ems_usb *dev)
> {
> int i;
>
> - usb_unlink_urb(dev->intr_urb);
> + usb_kill_urb(dev->intr_urb);
[Severity: Low]
Can this now log a spurious error during a normal ifdown?
usb_kill_urb() raises urb->reject before it unlinks the URB. Suppose the
intr URB completes with status 0 while ems_usb_close()->unlink_all_urbs()
is inside usb_kill_urb(). In that case ems_usb_read_interrupt_callback()
takes the case 0 path and resubmits:
ems_usb_read_interrupt_callback() {
...
err = usb_submit_urb(urb, GFP_ATOMIC);
if (err == -ENODEV)
netif_device_detach(netdev);
else if (err)
netdev_err(netdev, "failed resubmitting intr urb: %d\n", err);
}
usb_hcd_link_urb_to_ep() in drivers/usb/core/hcd.c then rejects the
resubmit:
/* Check that the URB isn't being killed */
if (unlikely(atomic_read(&urb->reject))) {
rc = -EPERM;
goto done;
}
As a result, "failed resubmitting intr urb: -1" gets printed. The
netif_device_present() check at the top of the callback doesn't catch
this, because the device is still present during close. usb_unlink_urb()
never set reject, so this message couldn't appear here before.
The kill itself still completes, so the only effect is log noise. Would it
make sense to treat -EPERM as an expected result, alongside -ENODEV?
>
> usb_kill_anchored_urbs(&dev->rx_submitted);
>
[Severity: Critical]
This isn't a bug introduced by this patch, but it is in the same helper
and the same disconnect teardown. Can unlink_all_urbs() free the RX
coherent buffers twice?
The loop just below this hunk frees every dev->rxbuf[i] but never clears
the pointers:
for (i = 0; i < MAX_RX_URBS; ++i)
usb_free_coherent(dev->udev, RX_BUFFER_SIZE,
dev->rxbuf[i], dev->rxbuf_dma[i]);
unlink_all_urbs() is called from ems_usb_close() and also unconditionally
from ems_usb_disconnect():
ems_usb_disconnect() {
...
unregister_netdev(dev->netdev);
unlink_all_urbs(dev);
...
}
There are three ways to reach a second free:
If the interface is up at unplug, unregister_netdev() closes it and
ems_usb_close()->unlink_all_urbs() frees the buffers. ems_usb_disconnect()
then calls unlink_all_urbs() again on the same pointers.
If the interface was opened and closed earlier and is down at unplug,
ems_usb_disconnect() frees the stale pointers from the last session a
second time.
If a later ems_usb_start() breaks out of the RX loop early because an
alloc or submit fails, the slots it didn't refill still hold pointers that
the previous close already freed. The next close or disconnect frees them
again.
usb_free_coherent() only skips a NULL addr, so each stale pointer goes to
hcd_buffer_free(). Depending on the HCD, that means dma_pool_free(),
kfree() or gen_pool_free() on memory that was already freed.
This loop appears to date from commit 9969e3c5f40c ("can: ems_usb: fix
memory leak").
Could dev->rxbuf[i] be set to NULL after each free, or could the extra
unlink_all_urbs() call in ems_usb_disconnect() be dropped?
[Severity: Medium]
This is a pre-existing issue, not one introduced by this patch. Does
ems_usb_start() leave URBs in flight when it fails part way through?
If usb_submit_urb(dev->intr_urb) fails, ems_usb_start() returns while the
RX URBs are still anchored on rx_submitted and in flight.
If a later ems_usb_control_cmd() or ems_usb_write_mode() call fails, it
returns with both the RX URBs and the self-resubmitting intr URB still
active:
failed:
netdev_warn(netdev, "couldn't submit control: %d\n", err);
return err;
On this path ems_usb_open() only calls close_candev(). ndo_stop isn't
called after a failed open, so unlink_all_urbs() never runs.
On the next open, ems_usb_start() overwrites dev->rxbuf[], so the earlier
buffers and URBs leak. usb_fill_int_urb() also rewrites the intr URB while
it is still active. usb_submit_urb() then hits:
if (urb->hcpriv) {
WARN_ONCE(1, "URB %p submitted while active\n", urb);
return -EBUSY;
}
>From then on every open fails until the device is replugged.
This doesn't reopen the disconnect use-after-free fixed here, because
ems_usb_disconnect()->unlink_all_urbs() now kills the leftover intr URB
before the frees.
Should ems_usb_start() unwind the submitted URBs on these error paths?
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20261015015336.816543-2-mkl%40pengutronix.de
next prev parent reply other threads:[~2026-10-16 2:37 UTC|newest]
Thread overview: 58+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-15 1:39 [PATCH net-next 0/37] pull-request: can-next 2026-10-15 Marc Kleine-Budde
2026-10-15 1:39 ` [PATCH net-next 01/37] can: dev: can_dropped_invalid_skb: drop CAN XL frames on non-CAN XL devices Marc Kleine-Budde
2026-10-15 1:57 ` netdev-bot+sinfo
2026-10-15 1:40 ` [PATCH net-next 02/37] can: raw: remove redundant NULL check before netdev_hold() Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 03/37] can: replace ARPHRD_CAN type checks with can_get_ml_priv() Marc Kleine-Budde
2026-10-16 2:37 ` netdev-bot+sashiko
2026-10-15 1:40 ` [PATCH net-next 04/37] can: proc: reset pkg_stats atomics individually Marc Kleine-Budde
2026-10-16 1:54 ` sashiko-bot
2026-10-16 2:37 ` netdev-bot+sashiko
2026-10-15 1:40 ` [PATCH net-next 05/37] can: proc: remove pointers from CAN specific proc output Marc Kleine-Budde
2026-10-16 2:37 ` netdev-bot+sashiko
2026-10-15 1:40 ` [PATCH net-next 06/37] can: isotp: check the frame type, not just the length Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 07/37] can: isotp: fix filter removal race between release and netns change Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 08/37] can: bcm: " Marc Kleine-Budde
2026-10-16 2:37 ` netdev-bot+sashiko
2026-10-15 1:40 ` [PATCH net-next 09/37] can: raw: take rtnl_lock() before leaving the notifier list Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 10/37] can: skb: make echo skb freeing safe in any IRQ context Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 11/37] dt-bindings: can: renesas,rcar-canfd: Document RZ/G3S SoC Marc Kleine-Budde
2026-10-16 2:37 ` netdev-bot+sashiko
2026-10-15 1:40 ` [PATCH net-next 12/37] can: skb: make CAN skb allocation failure paths IRQ-safe Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 13/37] can: rcar_canfd: Fix typos in macro names Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 14/37] can: dev: can_put_echo_skb(): free skb on invalid echo index Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 15/37] can: rcar_canfd: Allow the CAN FD clock to be sourced from fck Marc Kleine-Budde
2026-10-16 1:54 ` sashiko-bot
2026-10-16 2:37 ` netdev-bot+sashiko
2026-10-15 1:40 ` [PATCH net-next 16/37] can: rcar_canfd: Do not set registers selecting the CAN mode Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 17/37] can: rcar_canfd: Add support for Renesas RZ/G3S Marc Kleine-Budde
2026-10-16 1:54 ` sashiko-bot
2026-10-16 2:37 ` netdev-bot+sashiko
2026-10-15 1:40 ` [PATCH net-next 18/37] dt-bindings: can: renesas,rcar-canfd: Restrict resets in top-level Marc Kleine-Budde
2026-10-16 2:37 ` netdev-bot+sashiko
2026-10-15 1:40 ` [PATCH net-next 19/37] dt-bindings: can: renesas,rcar-canfd: Document RZ/G3L SoC Marc Kleine-Budde
2026-10-16 1:54 ` sashiko-bot
2026-10-16 2:37 ` netdev-bot+sashiko
2026-10-15 1:40 ` [PATCH net-next 20/37] can: rcar_canfd: Derive max_channels from the device tree Marc Kleine-Budde
2026-10-16 2:37 ` netdev-bot+sashiko
2026-10-15 1:40 ` [PATCH net-next 21/37] dt-bindings: net: can: convert grcan to DT schema Marc Kleine-Budde
2026-10-16 2:37 ` netdev-bot+sashiko
2026-10-15 1:40 ` [PATCH net-next 22/37] can: rcar_canfd: Add support for Renesas RZ/G3L Marc Kleine-Budde
2026-10-16 2:37 ` netdev-bot+sashiko
2026-10-15 1:40 ` [PATCH net-next 23/37] can: grcan: update the binding file reference in the driver comment Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 24/37] can: remove Softing CANcard driver Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 25/37] can: Convert to DEFINE_SIMPLE_DEV_PM_OPS() Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 26/37] can: cc770: don't discard the IRQ lookup error in probe Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 27/37] can: cc770: fix the clock divider check on the platform bus Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 28/37] can: ems_usb: use usb_kill_urb() to stop the intr URB Marc Kleine-Budde
2026-10-16 2:37 ` netdev-bot+sashiko [this message]
2026-10-15 1:40 ` [PATCH net-next 29/37] can: esd: acc_start_xmit(): avoid use-after-free of skb after can_put_echo_skb() Marc Kleine-Budde
2026-10-16 1:54 ` sashiko-bot
2026-10-15 1:40 ` [PATCH net-next 30/37] can: flexcan: flexcan_setup_stop_mode_gpr: fix OF node reference leak Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 31/37] can: kvaser_usb: refactor endpoint lookup Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 32/37] can: kvaser_usb: validate command format before parsing in hydra receive path Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 33/37] can: kvaser_pciefd: fix use-after-free in bec poll timer Marc Kleine-Budde
2026-10-16 1:54 ` sashiko-bot
2026-10-15 1:40 ` [PATCH net-next 34/37] can: mcp251xfd: mcp251xfd_probe(): reject devices without match data Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 35/37] can: sun4i_can: sun4ican_probe(): fix clk leak Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 36/37] can: ucan: fix repeated word 'is' in comment Marc Kleine-Budde
2026-10-15 1:40 ` [PATCH net-next 37/37] can: xilinx_can: set CAN FD flags on received frames Marc Kleine-Budde
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=179211823441.434549.9677243526506061190@kernel.org \
--to=netdev-bot+sashiko@kernel.org \
--cc=davem@davemloft.net \
--cc=kernel@pengutronix.de \
--cc=kuba@kernel.org \
--cc=kurt.van.dijck@eia.be \
--cc=linux-can@vger.kernel.org \
--cc=mkl@pengutronix.de \
--cc=netdev@vger.kernel.org \
--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