Thread (6 messages) 6 messages, 2 authors, 4d ago

[PATCH v2 2/2] nfc: pn533: add timeout to USB frame send completion wait

flat view
COOLING4d

From: Zhao Feng <hidden>
Date: 2026-10-27 07:01:40
Also in: lkml, stable
Subsystem: nfc subsystem, the rest · Maintainers: David Heidelberg, Linus Torvalds

pn533_usb_send_frame() waits unboundedly for the out URB to complete.
A device that never completes the transfer makes the task sleep
forever in TASK_UNINTERRUPTIBLE while holding the command mutex, as
reported by syzbot (hung task in pn533_usb_send_frame).

Use a 1 second timeout instead.  On timeout, kill the URB and return
-ETIMEDOUT so the command in progress fails gracefully instead of
hanging the task.

The transfer may complete between the timeout expiring and
usb_kill_urb(); in that case urb->status is 0 after the kill and the
send proceeds normally instead of reporting a spurious failure,
mirroring what usb_start_wait_urb() does.

Fixes: 9dab880d675b ("nfc: pn533: Wait for out_urb's completion in pn533_usb_send_frame()")
Reported-by: <redacted>
Closes: https://syzbot.org/bug?extid=1c5368988052dc2d8201
Signed-off-by: Zhao Feng <redacted>
Cc: <redacted>
---
v2: check urb->status after killing the URB on timeout and carry on if
    the transfer completed in the race window; add Fixes tag and Cc
    stable; the pn533_wq_cmd() error handling fix is now patch 1/2.
    Issues reported by the Sashiko AI review.

 drivers/nfc/pn533/usb.c | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/drivers/nfc/pn533/usb.c b/drivers/nfc/pn533/usb.c
index 0b7e3b118d..265baf2213 100644
--- a/drivers/nfc/pn533/usb.c
+++ b/drivers/nfc/pn533/usb.c
@@ -30,6 +30,9 @@
 #define ACS_VENDOR_ID 0x072f
 #define ACR122U_PRODUCT_ID 0x2200
 
+/* How long to wait for the out URB to complete */
+#define PN533_USB_SEND_TIMEOUT_MS	1000
+
 static const struct usb_device_id pn533_usb_table[] = {
 	{ USB_DEVICE(PN533_VENDOR_ID, PN533_PRODUCT_ID),
 	  .driver_info = PN533_DEVICE_STD },
@@ -184,8 +187,20 @@ static int pn533_usb_send_frame(struct pn533 *dev,
 	if (rc)
 		return rc;
 
-	wait_for_completion(&arg.done);
-	phy->out_urb->context = cntx;
+	if (!wait_for_completion_timeout(&arg.done,
+					 msecs_to_jiffies(PN533_USB_SEND_TIMEOUT_MS))) {
+		usb_kill_urb(phy->out_urb);
+		phy->out_urb->context = cntx;
+		/*
+		 * The transfer may have completed between the timeout
+		 * expiring and the urb being killed; if so, carry on as
+		 * usual instead of reporting a bogus failure.
+		 */
+		if (phy->out_urb->status)
+			return -ETIMEDOUT;
+	} else {
+		phy->out_urb->context = cntx;
+	}
 
 	if (dev->protocol_type == PN533_PROTO_REQ_RESP) {
 		/* request for response for sent packet directly */
-- 
2.39.2


Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help