]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob
868921912ee15e5a92903ab80b845d6ff68bdfda
[thirdparty/kernel/stable-queue.git] /
1 From 26d56a9fcb2014b99e654127960aa0a48a391e3c Mon Sep 17 00:00:00 2001
2 From: Owen Gu <guhuinan@xiaomi.com>
3 Date: Thu, 20 Nov 2025 20:33:36 +0800
4 Subject: usb: uas: fix urb unmapping issue when the uas device is remove during ongoing data transfer
5
6 From: Owen Gu <guhuinan@xiaomi.com>
7
8 commit 26d56a9fcb2014b99e654127960aa0a48a391e3c upstream.
9
10 When a UAS device is unplugged during data transfer, there is
11 a probability of a system panic occurring. The root cause is
12 an access to an invalid memory address during URB callback handling.
13 Specifically, this happens when the dma_direct_unmap_sg() function
14 is called within the usb_hcd_unmap_urb_for_dma() interface, but the
15 sg->dma_address field is 0 and the sg data structure has already been
16 freed.
17
18 The SCSI driver sends transfer commands by invoking uas_queuecommand_lck()
19 in uas.c, using the uas_submit_urbs() function to submit requests to USB.
20 Within the uas_submit_urbs() implementation, three URBs (sense_urb,
21 data_urb, and cmd_urb) are sequentially submitted. Device removal may
22 occur at any point during uas_submit_urbs execution, which may result
23 in URB submission failure. However, some URBs might have been successfully
24 submitted before the failure, and uas_submit_urbs will return the -ENODEV
25 error code in this case. The current error handling directly calls
26 scsi_done(). In the SCSI driver, this eventually triggers scsi_complete()
27 to invoke scsi_end_request() for releasing the sgtable. The successfully
28 submitted URBs, when being unlinked to giveback, call
29 usb_hcd_unmap_urb_for_dma() in hcd.c, leading to exceptions during sg
30 unmapping operations since the sg data structure has already been freed.
31
32 This patch modifies the error condition check in the uas_submit_urbs()
33 function. When a UAS device is removed but one or more URBs have already
34 been successfully submitted to USB, it avoids immediately invoking
35 scsi_done() and save the cmnd to devinfo->cmnd array. If the successfully
36 submitted URBs is completed before devinfo->resetting being set, then
37 the scsi_done() function will be called within uas_try_complete() after
38 all pending URB operations are finalized. Otherwise, the scsi_done()
39 function will be called within uas_zap_pending(), which is executed after
40 usb_kill_anchored_urbs().
41
42 The error handling only takes effect when uas_queuecommand_lck() calls
43 uas_submit_urbs() and returns the error value -ENODEV . In this case,
44 the device is disconnected, and the flow proceeds to uas_disconnect(),
45 where uas_zap_pending() is invoked to call uas_try_complete().
46
47 Fixes: eb2a86ae8c54 ("USB: UAS: fix disconnect by unplugging a hub")
48 Cc: stable <stable@kernel.org>
49 Signed-off-by: Yu Chen <chenyu45@xiaomi.com>
50 Signed-off-by: Owen Gu <guhuinan@xiaomi.com>
51 Acked-by: Oliver Neukum <oneukum@suse.com>
52 Link: https://patch.msgid.link/20251120123336.3328-1-guhuinan@xiaomi.com
53 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
54 ---
55 drivers/usb/storage/uas.c | 5 +++++
56 1 file changed, 5 insertions(+)
57
58 --- a/drivers/usb/storage/uas.c
59 +++ b/drivers/usb/storage/uas.c
60 @@ -698,6 +698,10 @@ static int uas_queuecommand_lck(struct s
61 * of queueing, no matter how fatal the error
62 */
63 if (err == -ENODEV) {
64 + if (cmdinfo->state & (COMMAND_INFLIGHT | DATA_IN_URB_INFLIGHT |
65 + DATA_OUT_URB_INFLIGHT))
66 + goto out;
67 +
68 set_host_byte(cmnd, DID_NO_CONNECT);
69 scsi_done(cmnd);
70 goto zombie;
71 @@ -711,6 +715,7 @@ static int uas_queuecommand_lck(struct s
72 uas_add_work(cmnd);
73 }
74
75 +out:
76 devinfo->cmnd[idx] = cmnd;
77 zombie:
78 spin_unlock_irqrestore(&devinfo->lock, flags);