From: David Laight <david.laight.linux@gmail.com>
To: netdev-bot+sashiko@kernel.org
Cc: omermetekaya0@gmail.com, netdev@vger.kernel.org,
oneukum@suse.com, andrew+netdev@lunn.ch, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
syzbot+04cd90bb99c6ef81a65d@syzkaller.appspotmail.com
Subject: Re: [PATCH net v4] usbnet: fix smp_processor_id() use in preemptible context
Date: Thu, 10 Sep 2026 10:01:22 +0100 [thread overview]
Message-ID: <20260910100122.205d2608@pumpkin> (raw)
In-Reply-To: <178899045475.219967.8804711454240391662@kernel.org>
On Wed, 09 Sep 2026 21:47:34 +0000
netdev-bot+sashiko@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential
> issue(s) to consider:
>
> Critical: 0 · High: 1 · Medium: 0 · Low: 0
>
> - [High] usbnet: dropping
> u64_stats_update_begin_irqsave()/u64_stats_update_end_irqrestore() in…
>
> --
>
> usbnet: fix smp_processor_id() use in preemptible context
>
> This changes usbnet_skb_return() and tx_complete() to fetch the per-CPU
> pcpu_sw_netstats pointer with get_cpu_ptr()/put_cpu_ptr() instead of a bare
> this_cpu_ptr(), addressing a smp_processor_id()-in-preemptible-code report
> from syzbot. Along with the pointer change it also switches the seqcount
> write helpers from the _irqsave variants to the plain ones.
>
> Closes: https://syzkaller.appspot.com/bug?extid=04cd90bb99c6ef81a65d
>
> > diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
> > index a19ecf718f36a..3df72b0c6bcfc 100644
> > --- a/drivers/net/usb/usbnet.c
> > +++ b/drivers/net/usb/usbnet.c
> > @@ -325,8 +325,7 @@ static void __usbnet_status_stop_force(struct usbnet *dev)
> > */
> > void usbnet_skb_return(struct usbnet *dev, struct sk_buff *skb)
> > {
> > - struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->net->tstats);
> > - unsigned long flags;
> > + struct pcpu_sw_netstats *stats64;
> > int status;
> >
> > if (test_bit(EVENT_RX_PAUSED, &dev->flags)) {
> > @@ -338,10 +337,12 @@ void usbnet_skb_return(struct usbnet *dev, struct sk_buff *skb)
> > if (skb->protocol == 0)
> > skb->protocol = eth_type_trans(skb, dev->net);
> >
> > - flags = u64_stats_update_begin_irqsave(&stats64->syncp);
> > + stats64 = get_cpu_ptr(dev->net->tstats);
> > + u64_stats_update_begin(&stats64->syncp);
> > u64_stats_inc(&stats64->rx_packets);
> > u64_stats_add(&stats64->rx_bytes, skb->len);
> > - u64_stats_update_end_irqrestore(&stats64->syncp, flags);
> > + u64_stats_update_end(&stats64->syncp);
> > + put_cpu_ptr(dev->net->tstats);
>
> [Severity: High]
>
> Does dropping the _irqsave seqcount helpers here re-open the problem that
> commit 2695578b896a ("net: usbnet: fix potential deadlock on 32bit hosts")
> closed?
Looks that way.
I think you need the following sequence:
local_irq_save(flags);
stats64 = this_cpu_ptr(...)
u64_stats_update_begin(...)
...
u64_stats_update_end(...);
local_irq_restore(flags);
David
>
> The reported splat is about the per-CPU pointer being taken outside of a
> preempt-disabled section, which get_cpu_ptr() addresses. But get_cpu_ptr()
> only disables preemption:
>
> include/linux/percpu-defs.h
> #define get_cpu_ptr(var) \
> ({ \
> preempt_disable(); \
> this_cpu_ptr(var); \
> })
>
> so nothing masks interrupts across the seqcount write section anymore.
>
> usbnet_skb_return() runs from usbnet_bh_work()->rx_process() (and from
> usbnet_resume_rx() in BH-disabled process context), i.e. with hardirqs
> enabled. tx_complete() below is the urb->complete callback, and for host
> controllers that do not set HCD_BH it is invoked straight from the
> controller's hardirq handler:
>
> drivers/usb/core/hcd.c:usb_hcd_giveback_urb() {
> if (!hcd_giveback_urb_in_bh(hcd) && !is_root_hub(urb->dev)) {
> __usb_hcd_giveback_urb(urb);
> return;
> }
> }
>
> drivers/usb/core/hcd.c:__usb_hcd_giveback_urb() {
> kcov_remote_start_usb_softirq((u64)urb->dev->bus->busnum);
> urb->complete(urb);
> kcov_remote_stop_softirq();
> }
>
> There is no local_irq_save() around urb->complete(). In-tree only
> ehci-hcd, xhci and dwc2 set HCD_BH, so on OHCI/UHCI/musb/max3421/sl811 and
> friends tx_complete() is a hardirq-context writer.
>
> Both sites write the same object, since struct pcpu_sw_netstats has a
> single u64_stats_sync shared by the rx and tx counters:
>
> include/linux/netdevice.h
> struct pcpu_sw_netstats {
> u64_stats_t rx_packets;
> u64_stats_t rx_bytes;
> u64_stats_t tx_packets;
> u64_stats_t tx_bytes;
> struct u64_stats_sync syncp;
> };
>
> On 32-bit, where u64_stats_sync is a real seqcount, can the following
> nesting happen on one CPU?
>
> usbnet_bh_work() -> rx_process() -> usbnet_skb_return()
> u64_stats_update_begin() /* seq odd, rx_bytes half written */
> <HCD hardirq>
> usb_hcd_giveback_urb() -> __usb_hcd_giveback_urb() -> tx_complete()
> u64_stats_update_begin() /* seq even again */
> u64_stats_update_end() /* seq odd */
> u64_stats_update_end() /* seq even */
>
> A reader coming in via dev_get_tstats64()->dev_fetch_sw_netstats() (for
> example "ip -s link show") would then see an even sequence in the middle of
> the outer update and accept a torn 64-bit counter without
> u64_stats_fetch_retry() firing. With lockdep on 32-bit, is this also the
> "inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W}" report that 2695578b896a
> removed?
>
> This is the constraint documented in include/linux/u64_stats_sync.h:
>
> * 3) Write side must use the _irqsave() variant if other writers, or a reader,
> * can be invoked from an IRQ context. On 64bit systems this variant does not
> * disable interrupts.
>
> Since the _irqsave variant compiles away on 64-bit, would it work to keep
> it and only change the pointer acquisition?
>
> stats64 = get_cpu_ptr(dev->net->tstats);
> flags = u64_stats_update_begin_irqsave(&stats64->syncp);
> u64_stats_inc(&stats64->rx_packets);
> u64_stats_add(&stats64->rx_bytes, skb->len);
> u64_stats_update_end_irqrestore(&stats64->syncp, flags);
> put_cpu_ptr(dev->net->tstats);
>
> The changelog only mentions the get_cpu_ptr()/put_cpu_ptr() conversion and
> says nothing about dropping the IRQ-safe helpers; could that be spelled out
> if the removal is intentional?
>
> >
> > netif_dbg(dev, rx_status, dev->net, "< rx, len %zu, type 0x%x\n",
> > skb->len + sizeof(struct ethhdr), skb->protocol);
> > @@ -1298,13 +1299,14 @@ static void tx_complete(struct urb *urb)
> > struct usbnet *dev = entry->dev;
> >
> > if (urb->status == 0) {
> > - struct pcpu_sw_netstats *stats64 = this_cpu_ptr(dev->net->tstats);
> > - unsigned long flags;
> > + struct pcpu_sw_netstats *stats64;
> >
> > - flags = u64_stats_update_begin_irqsave(&stats64->syncp);
> > + stats64 = get_cpu_ptr(dev->net->tstats);
> > + u64_stats_update_begin(&stats64->syncp);
> > u64_stats_add(&stats64->tx_packets, entry->packets);
> > u64_stats_add(&stats64->tx_bytes, entry->length);
> > - u64_stats_update_end_irqrestore(&stats64->syncp, flags);
> > + u64_stats_update_end(&stats64->syncp);
> > + put_cpu_ptr(dev->net->tstats);
> > } else {
>
> [ ... ]
>
next prev parent reply other threads:[~2026-09-10 9:01 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-03 16:54 [PATCH] usbnet: fix smp_processor_id() use in preemptible context Ömer Mete Kaya
2026-09-05 22:45 ` [PATCH net v2] " Ömer Mete Kaya
2026-09-07 11:38 ` Oliver Neukum
2026-09-07 18:52 ` Ömer Mete Kaya
2026-09-07 20:23 ` David Laight
2026-09-07 21:45 ` [PATCH net v4] " Ömer Mete Kaya
2026-09-09 21:47 ` netdev-bot+sashiko
2026-09-10 9:01 ` David Laight [this message]
2026-09-07 19:05 ` [PATCH] " Ömer Mete Kaya
2026-09-08 3:43 ` [PATCH net v2] " netdev-bot+sashiko
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=20260910100122.205d2608@pumpkin \
--to=david.laight.linux@gmail.com \
--cc=andrew+netdev@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=netdev-bot+sashiko@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=omermetekaya0@gmail.com \
--cc=oneukum@suse.com \
--cc=pabeni@redhat.com \
--cc=syzbot+04cd90bb99c6ef81a65d@syzkaller.appspotmail.com \
/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.