public inbox for linux-usb@vger.kernel.org
 help / color / mirror / Atom feed
* RFC: Prevent long uninterruptible waits in usbcore
@ 2026-02-09  2:33 Alan Stern
  2026-02-09 10:05 ` Greg KH
  0 siblings, 1 reply; 16+ messages in thread
From: Alan Stern @ 2026-02-09  2:33 UTC (permalink / raw)
  To: Greg KH, Oliver Neukum; +Cc: USB mailing list

I'm asking for comments on the patch below.  The problem it fixes is 
that usb_start_wait_urb(), which is used by utility routines like 
usb_bulk_msg() and usb_control_msg(), can have arbitrarily long 
uninterruptible waits.  And of course this can trigger the kernel's 
warning about a hung task.

Normally this isn't a problem, because drivers calling these routines 
generally specify timeouts on the order of 10 seconds or less.  In the 
particular case found by syzbot, however, the usbtmc driver uses a 
timeout value that it gets from an ioctl with no checking for 
excessively large numbers (see usbtmc_ioctl_set_timeout()).  We could 
change this one function, but what about other drivers?  There should be 
a single policy on how we handle these things.

Now, I suppose the reason that the usb_start_wait_urb() uses 
uninterruptible waits is that drivers don't want their calls to be 
interrupted and aren't prepared for that possibility.  But we also don't 
want them to tie up a kernel thread in a ridiculously long 
uninterruptible wait state.

I thought that a reasonable compromise would be to keep the 
uninterruptible waits for timeout periods less than 60 seconds (somewhat 
arbitrary, but hopefully short enough not to trigger the hung-task 
detector) and make them interruptible if the timeout is longer.  The 
idea is that long USB timeouts don't normally arise in the kernel, so 
they are probably caused by a user request (or a bad device), which 
would mean that interrupting them wouldn't be such a bad thing.

Any other ideas or thoughts about this?

Alan Stern

 drivers/usb/core/message.c |   22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

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);
 


^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2026-02-12  8:13 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-09  2:33 RFC: Prevent long uninterruptible waits in usbcore Alan Stern
2026-02-09 10:05 ` Greg KH
2026-02-09 15:16   ` Alan Stern
2026-02-09 15:39     ` Oliver Neukum
2026-02-09 19:59       ` [PATCH 1/2] usbcore: Reject excessively long uninterruptible timeouts Alan Stern
2026-02-09 20:00         ` [PATCH 2/2] USB: usbtmc: Don't accept very long timeouts Alan Stern
2026-02-10  9:03           ` Oliver Neukum
2026-02-11  3:25             ` Alan Stern
2026-02-11 10:28               ` Oliver Neukum
2026-02-11 15:31                 ` Alan Stern
2026-02-11 15:59                   ` Oliver Neukum
2026-02-11 16:18                     ` Alan Stern
2026-02-11 17:59                       ` Oliver Neukum
2026-02-12  2:34                         ` Alan Stern
2026-02-12  8:13                           ` Oliver Neukum
2026-02-10  8:51         ` [PATCH 1/2] usbcore: Reject excessively long uninterruptible timeouts Oliver Neukum

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox