From: syzbot <syzbot+9b95da55ba5146a60734@syzkaller.appspotmail.com>
To: linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com
Subject: Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue to fix RCU stall
Date: Sat, 04 Apr 2026 21:41:44 -0700 [thread overview]
Message-ID: <69d1e808.a70a0220.a26f2.001a.GAE@google.com> (raw)
In-Reply-To: <69cffde1.050a0220.182279.0016.GAE@google.com>
For archival purposes, forwarding an incoming command email to
linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com.
***
Subject: [PATCH] ath9k: defer reg_in URB resubmission to workqueue to fix RCU stall
Author: kartikey406@gmail.com
#syz test: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master
ath9k_hif_usb_reg_in_cb() is a URB completion callback that
runs in softirq context via dummy_hcd's hrtimer which is
registered with HRTIMER_MODE_REL_SOFT.
Calling usb_submit_urb() directly from this softirq context
triggers a long synchronous chain:
dummy_urb_enqueue()
hrtimer_start(HRTIMER_MODE_REL_SOFT)
dummy_timer()
__usb_hcd_giveback_urb()
ath9k_hif_usb_reg_in_cb()
usb_submit_urb() <- back to start
This keeps the CPU busy in softirq context indefinitely,
starving the rcu_preempt kthread and causing an RCU stall:
rcu: rcu_preempt kthread starved for 3053 jiffies!
rcu: Unless rcu_preempt kthread gets sufficient CPU time,
OOM is now expected behavior.
Fix this by introducing a small per-resubmission wrapper
struct (reg_in_work) that is freshly allocated on each URB
completion and carries its own work_struct. The resubmission
is then deferred to the system workqueue via schedule_work(),
allowing the softirq to exit quickly.
Using a fresh wrapper per completion avoids races that would
arise from reusing a single embedded work_struct:
- INIT_WORK() is called on a newly allocated struct so
there is no risk of reinitialising a work item that is
still queued or running.
- schedule_work() on a fresh work_struct always succeeds
so no resubmission is ever silently dropped.
- usb_get_urb() is called before schedule_work() and
usb_put_urb() is called last in the worker after all
URB accesses are complete, ensuring the URB remains
valid for the entire lifetime of the work item.
On resubmission failure in the worker the original error
path is preserved: skb and rx_buf are freed and
urb->context is set to NULL before dropping the URB
reference, matching the behaviour of the original
goto free_skb path.
Reported-by: syzbot+9b95da55ba5146a60734@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=9b95da55ba5146a60734
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
drivers/net/wireless/ath/ath9k/hif_usb.c | 53 ++++++++++++++++++++----
1 file changed, 45 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 8533b88974b2..0f9536b2d0a2 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -731,12 +731,43 @@ static void ath9k_hif_usb_rx_cb(struct urb *urb)
kfree(rx_buf);
}
+struct reg_in_work {
+ struct urb *urb;
+ struct hif_device_usb *hif_dev;
+ struct work_struct work;
+};
+
+static void ath9k_hif_usb_reg_in_resubmit(struct work_struct *work)
+{
+ struct reg_in_work *rw = container_of(work,
+ struct reg_in_work,
+ work);
+ struct urb *urb = rw->urb;
+ struct rx_buf *rx_buf = urb->context;
+
+ int ret;
+
+ usb_anchor_urb(rw->urb, &rw->hif_dev->reg_in_submitted);
+ ret = usb_submit_urb(rw->urb, GFP_KERNEL);
+
+ if (ret) {
+ usb_unanchor_urb(rw->urb);
+ if (rx_buf) {
+ kfree_skb(rx_buf->skb);
+ kfree(rx_buf);
+ urb->context = NULL;
+ }
+ }
+
+ usb_put_urb(urb);
+ kfree(rw);
+}
+
static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
{
struct rx_buf *rx_buf = urb->context;
struct hif_device_usb *hif_dev = rx_buf->hif_dev;
struct sk_buff *skb = rx_buf->skb;
- int ret;
if (!skb)
return;
@@ -786,14 +817,20 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb)
}
resubmit:
- usb_anchor_urb(urb, &hif_dev->reg_in_submitted);
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret) {
- usb_unanchor_urb(urb);
- goto free_skb;
+ {
+ struct reg_in_work *rw;
+
+ rw = kmalloc_obj(*rw, GFP_ATOMIC);
+ if (!rw)
+ goto free_skb;
+
+ rw->urb = urb;
+ rw->hif_dev = hif_dev;
+ usb_get_urb(urb);
+ INIT_WORK(&rw->work, ath9k_hif_usb_reg_in_resubmit);
+ schedule_work(&rw->work);
+ return;
}
-
- return;
free_skb:
kfree_skb(skb);
free_rx_buf:
--
2.43.0
next prev parent reply other threads:[~2026-04-05 4:41 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-03 17:50 [syzbot] [kernel?] INFO: rcu detected stall in kill syzbot
2026-04-05 1:21 ` Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue syzbot
2026-04-05 2:19 ` Forwarded: [PATCH] ath9k: defer reg_in URB resubmission to workqueue to fix RCU stall syzbot
2026-04-05 4:41 ` syzbot [this message]
2026-04-05 5:18 ` syzbot
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=69d1e808.a70a0220.a26f2.001a.GAE@google.com \
--to=syzbot+9b95da55ba5146a60734@syzkaller.appspotmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=syzkaller-bugs@googlegroups.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox