[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <0b508f72-7248-479c-ad26-b9385e52c094@rowland.harvard.edu>
Date: Sun, 8 Feb 2026 20:26:03 -0500
From: Alan Stern <stern@...land.harvard.edu>
To: syzbot <syzbot+25ba18e2c5040447585d@...kaller.appspotmail.com>
Cc: greearb@...delatech.com, hdanton@...a.com, linux-kernel@...r.kernel.org,
linux-usb@...r.kernel.org, michal.pecio@...il.com, oneukum@...e.com,
syzkaller-bugs@...glegroups.com
Subject: Re: [syzbot] [usb?] INFO: task hung in usb_bulk_msg (2)
On Sun, Feb 08, 2026 at 01:53:02PM -0800, syzbot wrote:
> Hello,
>
> syzbot has tested the proposed patch but the reproducer is still triggering an issue:
> INFO: task hung in usb_bulk_msg
All right, that clinches it. There's no problem with hardware or a
device driver; the problem is that a kernel thread is stuck in an
uninterruptible wait state for a very long time.
Hopefully this patch will prevent that from happening.
Alan Stern
#syz test: https://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git da87d45b1951
Index: usb-devel/drivers/usb/core/message.c
===================================================================
--- usb-devel.orig/drivers/usb/core/message.c
+++ usb-devel/drivers/usb/core/message.c
@@ -25,6 +25,8 @@
#include "usb.h"
+#define MAX_UNINTERRUPTIBLE_TIMEOUT_MS 60000
+
static void cancel_async_set_config(struct usb_device *udev);
struct api_context {
@@ -42,16 +44,16 @@ static void usb_api_blocking_completion(
/*
- * Starts urb and waits for completion or timeout. Note that this call
- * is NOT interruptible. Many device driver i/o requests should be
- * interruptible and therefore these drivers should implement their
- * own interruptible routines.
+ * Starts urb and waits for completion or timeout. Timeout lengths <= 0
+ * are taken to be as long as possible.
+ * The wait is NOT interruptible if the timeout period is no longer than
+ * MAX_UNINTERRUPTIBLE_TIMEOUT_MS, otherwise it IS interruptible.
*/
static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
{
struct api_context ctx;
unsigned long expire;
- int retval;
+ int rc, retval;
init_completion(&ctx.done);
urb->context = &ctx;
@@ -60,8 +62,14 @@ static int usb_start_wait_urb(struct urb
if (unlikely(retval))
goto out;
- expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
- if (!wait_for_completion_timeout(&ctx.done, expire)) {
+ expire = (timeout > 0) ? msecs_to_jiffies(timeout) :
+ MAX_SCHEDULE_TIMEOUT;
+ if (expire <= msecs_to_jiffies(MAX_UNINTERRUPTIBLE_TIMEOUT_MS))
+ rc = (wait_for_completion_timeout(&ctx.done, expire) > 0);
+ else
+ rc = (wait_for_completion_interruptible_timeout(
+ &ctx.done, expire) > 0);
+ if (!rc) {
usb_kill_urb(urb);
retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status);
Powered by blists - more mailing lists