From: Greg Kroah-Hartman Date: Mon, 13 Jul 2026 13:15:07 +0000 (+0200) Subject: 5.15-stable patches X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a30363e54c9b44b25f5b9da978eeb5133101df26;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: usb-xhci-fix-sleep-in-atomic-context-in-xhci_free_streams.patch --- diff --git a/queue-5.15/series b/queue-5.15/series index cffff76c3b..4d5062db52 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -79,3 +79,4 @@ bluetooth-btusb-fix-use-after-free-on-marvell-probe-failure.patch bluetooth-btusb-fix-wakeup-source-leak-on-probe-failure.patch binder-fix-uaf-in-binder_thread_release.patch binder-fix-uaf-in-binder_free_transaction.patch +usb-xhci-fix-sleep-in-atomic-context-in-xhci_free_streams.patch diff --git a/queue-5.15/usb-xhci-fix-sleep-in-atomic-context-in-xhci_free_streams.patch b/queue-5.15/usb-xhci-fix-sleep-in-atomic-context-in-xhci_free_streams.patch new file mode 100644 index 0000000000..cfa3c4b9e1 --- /dev/null +++ b/queue-5.15/usb-xhci-fix-sleep-in-atomic-context-in-xhci_free_streams.patch @@ -0,0 +1,86 @@ +From 42c37c4b75d38b51d84f31a8e29427f5e06a7c2a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?=E8=83=A1=E8=BF=9E=E5=8B=A4?= +Date: Fri, 3 Jul 2026 17:40:33 +0300 +Subject: usb: xhci: Fix sleep in atomic context in xhci_free_streams() + +From: 胡连勤 + +commit 42c37c4b75d38b51d84f31a8e29427f5e06a7c2a upstream. + +When a USB device with active stream endpoints is disconnected, +xhci_free_streams() is called from the hub_event workqueue to +free the stream resources. It calls xhci_free_stream_info() +while holding xhci->lock with irqs disabled. + +xhci_free_stream_info() invokes xhci_free_stream_ctx(), which +calls dma_free_coherent() for large stream context arrays. + +dma_free_coherent() can sleep (e.g. via vunmap), triggering +a BUG when called from atomic context. + +Call trace: + dma_free_attrs+0x174/0x220 + xhci_free_stream_info+0xd0/0x11c + xhci_free_streams+0x278/0x37c + usb_free_streams+0x98/0xc0 + usb_unbind_interface+0x1b8/0x2f8 + device_release_driver_internal+0x1d4/0x2cc + device_release_driver+0x18/0x28 + bus_remove_device+0x160/0x1a4 + device_del+0x1ec/0x350 + usb_disable_device+0x98/0x214 + usb_disconnect+0xf0/0x35c + hub_event+0xab4/0x19ec + process_one_work+0x278/0x63c + +Fix this by saving the stream_info pointers and clearing the +ep references under the lock, then calling xhci_free_stream_info() +outside the lock where sleeping is allowed. + +Fixes: 8df75f42f8e6 ("USB: xhci: Add memory allocation for USB3 bulk streams.") +Cc: stable +Signed-off-by: Lianqin Hu +Signed-off-by: Mathias Nyman +Link: https://patch.msgid.link/20260703144033.483286-3-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -3710,6 +3710,7 @@ static int xhci_free_streams(struct usb_ + struct xhci_virt_device *vdev; + struct xhci_command *command; + struct xhci_input_control_ctx *ctrl_ctx; ++ struct xhci_stream_info *stream_info[EP_CTX_PER_DEV]; + unsigned int ep_index; + unsigned long flags; + u32 changed_ep_bitmask; +@@ -3770,10 +3771,15 @@ static int xhci_free_streams(struct usb_ + if (ret < 0) + return ret; + ++ /* ++ * dma_free_coherent() called by xhci_free_stream_info() may sleep, ++ * so save stream_info pointers and clear references under lock, ++ * then free the memory outside lock. ++ */ + spin_lock_irqsave(&xhci->lock, flags); + for (i = 0; i < num_eps; i++) { + ep_index = xhci_get_endpoint_index(&eps[i]->desc); +- xhci_free_stream_info(xhci, vdev->eps[ep_index].stream_info); ++ stream_info[i] = vdev->eps[ep_index].stream_info; + vdev->eps[ep_index].stream_info = NULL; + /* FIXME Unset maxPstreams in endpoint context and + * update deq ptr to point to normal string ring. +@@ -3783,6 +3789,9 @@ static int xhci_free_streams(struct usb_ + } + spin_unlock_irqrestore(&xhci->lock, flags); + ++ for (i = 0; i < num_eps; i++) ++ xhci_free_stream_info(xhci, stream_info[i]); ++ + return 0; + } +