From: Greg Kroah-Hartman Date: Mon, 16 Mar 2026 15:53:58 +0000 (+0100) Subject: 5.15-stable patches X-Git-Tag: v6.18.19~74 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=20239be53da5518d7b01f3ad54d123fd55dc3bb3;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: usb-cdc-acm-restore-cap_brk-functionnality-to-ch343.patch usb-class-cdc-wdm-fix-reordering-issue-in-read-code-path.patch usb-core-don-t-power-off-roothub-phys-if-phy_set_mode-fails.patch usb-core-limit-the-length-of-unkillable-synchronous-timeouts.patch usb-core-quirks-add-huawei-me906s-device-to-wakeup-quirk.patch usb-image-mdc800-kill-download-urb-on-timeout.patch usb-mdc800-handle-signal-and-read-racing.patch usb-misc-uss720-properly-clean-up-reference-in-uss720_probe.patch usb-renesas_usbhs-fix-use-after-free-in-isr-during-device-removal.patch usb-usbcore-introduce-usb_bulk_msg_killable.patch usb-usbtmc-use-usb_bulk_msg_killable-with-user-specified-timeouts.patch usb-xhci-fix-memory-leak-in-xhci_disable_slot.patch usb-yurex-fix-race-in-probe.patch --- diff --git a/queue-5.15/series b/queue-5.15/series index ee212ef55d..36ee1a9e3c 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -131,3 +131,16 @@ revert-arm64-dts-qcom-sdm845-oneplus-mark-l14a-regul.patch cgroup-fix-race-between-task-migration-and-iteration.patch net-usb-lan78xx-fix-silent-drop-of-packets-with-checksum-errors.patch net-usb-lan78xx-skip-ltm-configuration-for-lan7850.patch +usb-core-quirks-add-huawei-me906s-device-to-wakeup-quirk.patch +usb-xhci-fix-memory-leak-in-xhci_disable_slot.patch +usb-yurex-fix-race-in-probe.patch +usb-misc-uss720-properly-clean-up-reference-in-uss720_probe.patch +usb-core-don-t-power-off-roothub-phys-if-phy_set_mode-fails.patch +usb-cdc-acm-restore-cap_brk-functionnality-to-ch343.patch +usb-usbcore-introduce-usb_bulk_msg_killable.patch +usb-usbtmc-use-usb_bulk_msg_killable-with-user-specified-timeouts.patch +usb-core-limit-the-length-of-unkillable-synchronous-timeouts.patch +usb-class-cdc-wdm-fix-reordering-issue-in-read-code-path.patch +usb-renesas_usbhs-fix-use-after-free-in-isr-during-device-removal.patch +usb-mdc800-handle-signal-and-read-racing.patch +usb-image-mdc800-kill-download-urb-on-timeout.patch diff --git a/queue-5.15/usb-cdc-acm-restore-cap_brk-functionnality-to-ch343.patch b/queue-5.15/usb-cdc-acm-restore-cap_brk-functionnality-to-ch343.patch new file mode 100644 index 0000000000..dd72a42f22 --- /dev/null +++ b/queue-5.15/usb-cdc-acm-restore-cap_brk-functionnality-to-ch343.patch @@ -0,0 +1,62 @@ +From 14ae24cba291bddfdc296bbcbfd00cd09d0498ef Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Sun, 1 Mar 2026 12:44:40 +0000 +Subject: usb: cdc-acm: Restore CAP_BRK functionnality to CH343 + +From: Marc Zyngier + +commit 14ae24cba291bddfdc296bbcbfd00cd09d0498ef upstream. + +The CH343 USB/serial adapter is as buggy as it is popular (very). +One of its quirks is that despite being capable of signalling a +BREAK condition, it doesn't advertise it. + +This used to work nonetheless until 66aad7d8d3ec5 ("usb: cdc-acm: +return correct error code on unsupported break") applied some +reasonable restrictions, preventing breaks from being emitted on +devices that do not advertise CAP_BRK. + +Add a quirk for this particular device, so that breaks can still +be produced on some of my machines attached to my console server. + +Fixes: 66aad7d8d3ec5 ("usb: cdc-acm: return correct error code on unsupported break") +Signed-off-by: Marc Zyngier +Cc: stable +Cc: Oliver Neukum +Cc: Greg Kroah-Hartman +Acked-by: Oliver Neukum +Link: https://patch.msgid.link/20260301124440.1192752-1-maz@kernel.org +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/class/cdc-acm.c | 5 +++++ + drivers/usb/class/cdc-acm.h | 1 + + 2 files changed, 6 insertions(+) + +--- a/drivers/usb/class/cdc-acm.c ++++ b/drivers/usb/class/cdc-acm.c +@@ -1359,6 +1359,8 @@ made_compressed_probe: + acm->ctrl_caps = h.usb_cdc_acm_descriptor->bmCapabilities; + if (quirks & NO_CAP_LINE) + acm->ctrl_caps &= ~USB_CDC_CAP_LINE; ++ if (quirks & MISSING_CAP_BRK) ++ acm->ctrl_caps |= USB_CDC_CAP_BRK; + acm->ctrlsize = ctrlsize; + acm->readsize = readsize; + acm->rx_buflimit = num_rx_buf; +@@ -1988,6 +1990,9 @@ static const struct usb_device_id acm_id + .driver_info = IGNORE_DEVICE, + }, + ++ /* CH343 supports CAP_BRK, but doesn't advertise it */ ++ { USB_DEVICE(0x1a86, 0x55d3), .driver_info = MISSING_CAP_BRK, }, ++ + /* control interfaces without any protocol set */ + { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, + USB_CDC_PROTO_NONE) }, +--- a/drivers/usb/class/cdc-acm.h ++++ b/drivers/usb/class/cdc-acm.h +@@ -141,3 +141,4 @@ struct acm { + #define CLEAR_HALT_CONDITIONS BIT(5) + #define SEND_ZERO_PACKET BIT(6) + #define DISABLE_ECHO BIT(7) ++#define MISSING_CAP_BRK BIT(8) diff --git a/queue-5.15/usb-class-cdc-wdm-fix-reordering-issue-in-read-code-path.patch b/queue-5.15/usb-class-cdc-wdm-fix-reordering-issue-in-read-code-path.patch new file mode 100644 index 0000000000..63c6ae265f --- /dev/null +++ b/queue-5.15/usb-class-cdc-wdm-fix-reordering-issue-in-read-code-path.patch @@ -0,0 +1,50 @@ +From 8df672bfe3ec2268c2636584202755898e547173 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Wed, 4 Mar 2026 14:01:12 +0100 +Subject: usb: class: cdc-wdm: fix reordering issue in read code path + +From: Oliver Neukum + +commit 8df672bfe3ec2268c2636584202755898e547173 upstream. + +Quoting the bug report: + +Due to compiler optimization or CPU out-of-order execution, the +desc->length update can be reordered before the memmove. If this +happens, wdm_read() can see the new length and call copy_to_user() on +uninitialized memory. This also violates LKMM data race rules [1]. + +Fix it by using WRITE_ONCE and memory barriers. + +Fixes: afba937e540c9 ("USB: CDC WDM driver") +Cc: stable +Signed-off-by: Oliver Neukum +Closes: https://lore.kernel.org/linux-usb/CALbr=LbrUZn_cfp7CfR-7Z5wDTHF96qeuM=3fO2m-q4cDrnC4A@mail.gmail.com/ +Reported-by: Gui-Dong Han +Reviewed-by: Gui-Dong Han +Link: https://patch.msgid.link/20260304130116.1721682-1-oneukum@suse.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/class/cdc-wdm.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/class/cdc-wdm.c ++++ b/drivers/usb/class/cdc-wdm.c +@@ -225,7 +225,8 @@ static void wdm_in_callback(struct urb * + /* we may already be in overflow */ + if (!test_bit(WDM_OVERFLOW, &desc->flags)) { + memmove(desc->ubuf + desc->length, desc->inbuf, length); +- desc->length += length; ++ smp_wmb(); /* against wdm_read() */ ++ WRITE_ONCE(desc->length, desc->length + length); + } + } + skip_error: +@@ -533,6 +534,7 @@ static ssize_t wdm_read + return -ERESTARTSYS; + + cntr = READ_ONCE(desc->length); ++ smp_rmb(); /* against wdm_in_callback() */ + if (cntr == 0) { + desc->read = 0; + retry: diff --git a/queue-5.15/usb-core-don-t-power-off-roothub-phys-if-phy_set_mode-fails.patch b/queue-5.15/usb-core-don-t-power-off-roothub-phys-if-phy_set_mode-fails.patch new file mode 100644 index 0000000000..960ad08711 --- /dev/null +++ b/queue-5.15/usb-core-don-t-power-off-roothub-phys-if-phy_set_mode-fails.patch @@ -0,0 +1,50 @@ +From e293015ba76eb96ce4ebed7e3b2cb1a7d319f3e9 Mon Sep 17 00:00:00 2001 +From: Gabor Juhos +Date: Wed, 18 Feb 2026 21:21:07 +0100 +Subject: usb: core: don't power off roothub PHYs if phy_set_mode() fails + +From: Gabor Juhos + +commit e293015ba76eb96ce4ebed7e3b2cb1a7d319f3e9 upstream. + +Remove the error path from the usb_phy_roothub_set_mode() function. +The code is clearly wrong, because phy_set_mode() calls can't be +balanced with phy_power_off() calls. + +Additionally, the usb_phy_roothub_set_mode() function is called only +from usb_add_hcd() before it powers on the PHYs, so powering off those +makes no sense anyway. + +Presumably, the code is copy-pasted from the phy_power_on() function +without adjusting the error handling. + +Cc: stable@vger.kernel.org # v5.1+ +Fixes: b97a31348379 ("usb: core: comply to PHY framework") +Signed-off-by: Gabor Juhos +Reviewed-by: Miquel Raynal +Link: https://patch.msgid.link/20260218-usb-phy-poweroff-fix-v1-1-66e6831e860e@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/phy.c | 8 +------- + 1 file changed, 1 insertion(+), 7 deletions(-) + +--- a/drivers/usb/core/phy.c ++++ b/drivers/usb/core/phy.c +@@ -138,16 +138,10 @@ int usb_phy_roothub_set_mode(struct usb_ + list_for_each_entry(roothub_entry, head, list) { + err = phy_set_mode(roothub_entry->phy, mode); + if (err) +- goto err_out; ++ return err; + } + + return 0; +- +-err_out: +- list_for_each_entry_continue_reverse(roothub_entry, head, list) +- phy_power_off(roothub_entry->phy); +- +- return err; + } + EXPORT_SYMBOL_GPL(usb_phy_roothub_set_mode); + diff --git a/queue-5.15/usb-core-limit-the-length-of-unkillable-synchronous-timeouts.patch b/queue-5.15/usb-core-limit-the-length-of-unkillable-synchronous-timeouts.patch new file mode 100644 index 0000000000..56eb60b7c1 --- /dev/null +++ b/queue-5.15/usb-core-limit-the-length-of-unkillable-synchronous-timeouts.patch @@ -0,0 +1,134 @@ +From 1015c27a5e1a63efae2b18a9901494474b4d1dc3 Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Tue, 17 Feb 2026 22:10:32 -0500 +Subject: USB: core: Limit the length of unkillable synchronous timeouts + +From: Alan Stern + +commit 1015c27a5e1a63efae2b18a9901494474b4d1dc3 upstream. + +The usb_control_msg(), usb_bulk_msg(), and usb_interrupt_msg() APIs in +usbcore allow unlimited timeout durations. And since they use +uninterruptible waits, this leaves open the possibility of hanging a +task for an indefinitely long time, with no way to kill it short of +unplugging the target device. + +To prevent this sort of problem, enforce a maximum limit on the length +of these unkillable timeouts. The limit chosen here, somewhat +arbitrarily, is 60 seconds. On many systems (although not all) this +is short enough to avoid triggering the kernel's hung-task detector. + +In addition, clear up the ambiguity of negative timeout values by +treating them the same as 0, i.e., using the maximum allowed timeout. + +Signed-off-by: Alan Stern +Link: https://lore.kernel.org/linux-usb/3acfe838-6334-4f6d-be7c-4bb01704b33d@rowland.harvard.edu/ +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +CC: stable@vger.kernel.org +Link: https://patch.msgid.link/15fc9773-a007-47b0-a703-df89a8cf83dd@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/message.c | 27 +++++++++++++-------------- + include/linux/usb.h | 3 +++ + 2 files changed, 16 insertions(+), 14 deletions(-) + +--- a/drivers/usb/core/message.c ++++ b/drivers/usb/core/message.c +@@ -44,6 +44,8 @@ static void usb_api_blocking_completion( + * Starts urb and waits for completion or timeout. + * Whether or not the wait is killable depends on the flag passed in. + * For example, compare usb_bulk_msg() and usb_bulk_msg_killable(). ++ * ++ * For non-killable waits, we enforce a maximum limit on the timeout value. + */ + static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length, + bool killable) +@@ -60,7 +62,9 @@ static int usb_start_wait_urb(struct urb + if (unlikely(retval)) + goto out; + +- expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; ++ if (!killable && (timeout <= 0 || timeout > USB_MAX_SYNCHRONOUS_TIMEOUT)) ++ timeout = USB_MAX_SYNCHRONOUS_TIMEOUT; ++ expire = (timeout > 0) ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; + if (killable) + rc = wait_for_completion_killable_timeout(&ctx.done, expire); + else +@@ -126,8 +130,7 @@ static int usb_internal_control_msg(stru + * @index: USB message index value + * @data: pointer to the data to send + * @size: length in bytes of the data to send +- * @timeout: time in msecs to wait for the message to complete before timing +- * out (if 0 the wait is forever) ++ * @timeout: time in msecs to wait for the message to complete before timing out + * + * Context: task context, might sleep. + * +@@ -182,8 +185,7 @@ EXPORT_SYMBOL_GPL(usb_control_msg); + * @index: USB message index value + * @driver_data: pointer to the data to send + * @size: length in bytes of the data to send +- * @timeout: time in msecs to wait for the message to complete before timing +- * out (if 0 the wait is forever) ++ * @timeout: time in msecs to wait for the message to complete before timing out + * @memflags: the flags for memory allocation for buffers + * + * Context: !in_interrupt () +@@ -241,8 +243,7 @@ EXPORT_SYMBOL_GPL(usb_control_msg_send); + * @index: USB message index value + * @driver_data: pointer to the data to be filled in by the message + * @size: length in bytes of the data to be received +- * @timeout: time in msecs to wait for the message to complete before timing +- * out (if 0 the wait is forever) ++ * @timeout: time in msecs to wait for the message to complete before timing out + * @memflags: the flags for memory allocation for buffers + * + * Context: !in_interrupt () +@@ -313,8 +314,7 @@ EXPORT_SYMBOL_GPL(usb_control_msg_recv); + * @len: length in bytes of the data to send + * @actual_length: pointer to a location to put the actual length transferred + * in bytes +- * @timeout: time in msecs to wait for the message to complete before +- * timing out (if 0 the wait is forever) ++ * @timeout: time in msecs to wait for the message to complete before timing out + * + * Context: task context, might sleep. + * +@@ -346,8 +346,7 @@ EXPORT_SYMBOL_GPL(usb_interrupt_msg); + * @len: length in bytes of the data to send + * @actual_length: pointer to a location to put the actual length transferred + * in bytes +- * @timeout: time in msecs to wait for the message to complete before +- * timing out (if 0 the wait is forever) ++ * @timeout: time in msecs to wait for the message to complete before timing out + * + * Context: task context, might sleep. + * +@@ -407,12 +406,12 @@ EXPORT_SYMBOL_GPL(usb_bulk_msg); + * @actual_length: pointer to a location to put the actual length transferred + * in bytes + * @timeout: time in msecs to wait for the message to complete before +- * timing out (if 0 the wait is forever) ++ * timing out (if <= 0, the wait is as long as possible) + * + * Context: task context, might sleep. + * +- * This function is just like usb_blk_msg() except that it waits in a +- * killable state. ++ * This function is just like usb_blk_msg(), except that it waits in a ++ * killable state and there is no limit on the timeout length. + * + * Return: + * If successful, 0. Otherwise a negative error number. The number of actual +--- a/include/linux/usb.h ++++ b/include/linux/usb.h +@@ -1805,6 +1805,9 @@ void usb_buffer_unmap_sg(const struct us + * SYNCHRONOUS CALL SUPPORT * + *-------------------------------------------------------------------*/ + ++/* Maximum value allowed for timeout in synchronous routines below */ ++#define USB_MAX_SYNCHRONOUS_TIMEOUT 60000 /* ms */ ++ + extern int usb_control_msg(struct usb_device *dev, unsigned int pipe, + __u8 request, __u8 requesttype, __u16 value, __u16 index, + void *data, __u16 size, int timeout); diff --git a/queue-5.15/usb-core-quirks-add-huawei-me906s-device-to-wakeup-quirk.patch b/queue-5.15/usb-core-quirks-add-huawei-me906s-device-to-wakeup-quirk.patch new file mode 100644 index 0000000000..f65e138d87 --- /dev/null +++ b/queue-5.15/usb-core-quirks-add-huawei-me906s-device-to-wakeup-quirk.patch @@ -0,0 +1,36 @@ +From 0326ff28d56b4fa202de36ffc8462a354f383a64 Mon Sep 17 00:00:00 2001 +From: Christoffer Sandberg +Date: Fri, 6 Mar 2026 18:28:14 +0100 +Subject: usb/core/quirks: Add Huawei ME906S-device to wakeup quirk + +From: Christoffer Sandberg + +commit 0326ff28d56b4fa202de36ffc8462a354f383a64 upstream. + +Similar to other Huawei LTE modules using this quirk, this version with +another vid/pid suffers from spurious wakeups. + +Setting the quirk fixes the issue for this device as well. + +Cc: stable +Signed-off-by: Christoffer Sandberg +Signed-off-by: Werner Sembach +Link: https://patch.msgid.link/20260306172817.2098898-1-wse@tuxedocomputers.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/quirks.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/usb/core/quirks.c ++++ b/drivers/usb/core/quirks.c +@@ -205,6 +205,10 @@ static const struct usb_device_id usb_qu + /* HP v222w 16GB Mini USB Drive */ + { USB_DEVICE(0x03f0, 0x3f40), .driver_info = USB_QUIRK_DELAY_INIT }, + ++ /* Huawei 4G LTE module ME906S */ ++ { USB_DEVICE(0x03f0, 0xa31d), .driver_info = ++ USB_QUIRK_DISCONNECT_SUSPEND }, ++ + /* Creative SB Audigy 2 NX */ + { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, + diff --git a/queue-5.15/usb-image-mdc800-kill-download-urb-on-timeout.patch b/queue-5.15/usb-image-mdc800-kill-download-urb-on-timeout.patch new file mode 100644 index 0000000000..aa05bc0b49 --- /dev/null +++ b/queue-5.15/usb-image-mdc800-kill-download-urb-on-timeout.patch @@ -0,0 +1,49 @@ +From 1be3b77de4eb89af8ae2fd6610546be778e25589 Mon Sep 17 00:00:00 2001 +From: Ziyi Guo +Date: Mon, 9 Feb 2026 15:19:37 +0000 +Subject: usb: image: mdc800: kill download URB on timeout + +From: Ziyi Guo + +commit 1be3b77de4eb89af8ae2fd6610546be778e25589 upstream. + +mdc800_device_read() submits download_urb and waits for completion. +If the timeout fires and the device has not responded, the function +returns without killing the URB, leaving it active. + +A subsequent read() resubmits the same URB while it is still +in-flight, triggering the WARN in usb_submit_urb(): + + "URB submitted while active" + +Check the return value of wait_event_timeout() and kill the URB if +it indicates timeout, ensuring the URB is complete before its status +is inspected or the URB is resubmitted. + +Similar to +- commit 372c93131998 ("USB: yurex: fix control-URB timeout handling") +- commit b98d5000c505 ("media: rc: iguanair: handle timeouts") + +Signed-off-by: Ziyi Guo +Cc: stable +Link: https://patch.msgid.link/20260209151937.2247202-1-n7l8m4@u.northwestern.edu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/image/mdc800.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +--- a/drivers/usb/image/mdc800.c ++++ b/drivers/usb/image/mdc800.c +@@ -731,9 +731,11 @@ static ssize_t mdc800_device_read (struc + mutex_unlock(&mdc800->io_lock); + return len-left; + } +- wait_event_timeout(mdc800->download_wait, ++ retval = wait_event_timeout(mdc800->download_wait, + mdc800->downloaded, + msecs_to_jiffies(TO_DOWNLOAD_GET_READY)); ++ if (!retval) ++ usb_kill_urb(mdc800->download_urb); + mdc800->downloaded = 0; + if (mdc800->download_urb->status != 0) + { diff --git a/queue-5.15/usb-mdc800-handle-signal-and-read-racing.patch b/queue-5.15/usb-mdc800-handle-signal-and-read-racing.patch new file mode 100644 index 0000000000..359c0a7ebf --- /dev/null +++ b/queue-5.15/usb-mdc800-handle-signal-and-read-racing.patch @@ -0,0 +1,32 @@ +From 2d6d260e9a3576256fe9ef6d1f7930c9ec348723 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Mon, 9 Feb 2026 15:20:48 +0100 +Subject: usb: mdc800: handle signal and read racing + +From: Oliver Neukum + +commit 2d6d260e9a3576256fe9ef6d1f7930c9ec348723 upstream. + +If a signal arrives after a read has partially completed, +we need to return the number of bytes read. -EINTR is correct +only if that number is zero. + +Signed-off-by: Oliver Neukum +Cc: stable +Link: https://patch.msgid.link/20260209142048.1503791-1-oneukum@suse.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/image/mdc800.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/image/mdc800.c ++++ b/drivers/usb/image/mdc800.c +@@ -708,7 +708,7 @@ static ssize_t mdc800_device_read (struc + if (signal_pending (current)) + { + mutex_unlock(&mdc800->io_lock); +- return -EINTR; ++ return len == left ? -EINTR : len-left; + } + + sts=left > (mdc800->out_count-mdc800->out_ptr)?mdc800->out_count-mdc800->out_ptr:left; diff --git a/queue-5.15/usb-misc-uss720-properly-clean-up-reference-in-uss720_probe.patch b/queue-5.15/usb-misc-uss720-properly-clean-up-reference-in-uss720_probe.patch new file mode 100644 index 0000000000..f7378c1d27 --- /dev/null +++ b/queue-5.15/usb-misc-uss720-properly-clean-up-reference-in-uss720_probe.patch @@ -0,0 +1,33 @@ +From 45dba8011efac11a2f360383221b541f5ea53ce5 Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Mon, 23 Feb 2026 13:19:43 +0100 +Subject: usb: misc: uss720: properly clean up reference in uss720_probe() + +From: Greg Kroah-Hartman + +commit 45dba8011efac11a2f360383221b541f5ea53ce5 upstream. + +If get_1284_register() fails, the usb device reference count is +incorrect and needs to be properly dropped before returning. That will +happen when the kref is dropped in the call to destroy_priv(), so jump +to that error path instead of returning directly. + +Cc: stable +Assisted-by: gkh_clanker_2000 +Link: https://patch.msgid.link/2026022342-smokiness-stove-d792@gregkh +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/uss720.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/misc/uss720.c ++++ b/drivers/usb/misc/uss720.c +@@ -733,7 +733,7 @@ static int uss720_probe(struct usb_inter + ret = get_1284_register(pp, 0, ®, GFP_KERNEL); + dev_dbg(&intf->dev, "reg: %7ph\n", priv->reg); + if (ret < 0) +- return ret; ++ goto probe_abort; + + ret = usb_find_last_int_in_endpoint(interface, &epd); + if (!ret) { diff --git a/queue-5.15/usb-renesas_usbhs-fix-use-after-free-in-isr-during-device-removal.patch b/queue-5.15/usb-renesas_usbhs-fix-use-after-free-in-isr-during-device-removal.patch new file mode 100644 index 0000000000..10c4b7c1c9 --- /dev/null +++ b/queue-5.15/usb-renesas_usbhs-fix-use-after-free-in-isr-during-device-removal.patch @@ -0,0 +1,46 @@ +From 3cbc242b88c607f55da3d0d0d336b49bf1e20412 Mon Sep 17 00:00:00 2001 +From: Fan Wu +Date: Tue, 3 Mar 2026 07:33:44 +0000 +Subject: usb: renesas_usbhs: fix use-after-free in ISR during device removal + +From: Fan Wu + +commit 3cbc242b88c607f55da3d0d0d336b49bf1e20412 upstream. + +In usbhs_remove(), the driver frees resources (including the pipe array) +while the interrupt handler (usbhs_interrupt) is still registered. If an +interrupt fires after usbhs_pipe_remove() but before the driver is fully +unbound, the ISR may access freed memory, causing a use-after-free. + +Fix this by calling devm_free_irq() before freeing resources. This ensures +the interrupt handler is both disabled and synchronized (waits for any +running ISR to complete) before usbhs_pipe_remove() is called. + +Fixes: f1407d5c6624 ("usb: renesas_usbhs: Add Renesas USBHS common code") +Cc: stable +Suggested-by: Alan Stern +Signed-off-by: Fan Wu +Link: https://patch.msgid.link/20260303073344.34577-1-fanwu01@zju.edu.cn +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/renesas_usbhs/common.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/usb/renesas_usbhs/common.c ++++ b/drivers/usb/renesas_usbhs/common.c +@@ -804,6 +804,15 @@ static void usbhs_remove(struct platform + + usbhs_platform_call(priv, hardware_exit, pdev); + reset_control_assert(priv->rsts); ++ ++ /* ++ * Explicitly free the IRQ to ensure the interrupt handler is ++ * disabled and synchronized before freeing resources. ++ * devm_free_irq() calls free_irq() which waits for any running ++ * ISR to complete, preventing UAF. ++ */ ++ devm_free_irq(&pdev->dev, priv->irq, priv); ++ + usbhs_mod_remove(priv); + usbhs_fifo_remove(priv); + usbhs_pipe_remove(priv); diff --git a/queue-5.15/usb-usbcore-introduce-usb_bulk_msg_killable.patch b/queue-5.15/usb-usbcore-introduce-usb_bulk_msg_killable.patch new file mode 100644 index 0000000000..e8ac81c178 --- /dev/null +++ b/queue-5.15/usb-usbcore-introduce-usb_bulk_msg_killable.patch @@ -0,0 +1,166 @@ +From 416909962e7cdf29fd01ac523c953f37708df93d Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Tue, 17 Feb 2026 22:07:47 -0500 +Subject: USB: usbcore: Introduce usb_bulk_msg_killable() + +From: Alan Stern + +commit 416909962e7cdf29fd01ac523c953f37708df93d upstream. + +The synchronous message API in usbcore (usb_control_msg(), +usb_bulk_msg(), and so on) uses uninterruptible waits. However, +drivers may call these routines in the context of a user thread, which +means it ought to be possible to at least kill them. + +For this reason, introduce a new usb_bulk_msg_killable() function +which behaves the same as usb_bulk_msg() except for using +wait_for_completion_killable_timeout() instead of +wait_for_completion_timeout(). The same can be done later for +usb_control_msg() later on, if it turns out to be needed. + +Signed-off-by: Alan Stern +Suggested-by: Oliver Neukum +Link: https://lore.kernel.org/linux-usb/3acfe838-6334-4f6d-be7c-4bb01704b33d@rowland.harvard.edu/ +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +CC: stable@vger.kernel.org +Link: https://patch.msgid.link/248628b4-cc83-4e81-a620-3ce4e0376d41@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/core/message.c | 79 +++++++++++++++++++++++++++++++++++++++------ + include/linux/usb.h | 5 +- + 2 files changed, 72 insertions(+), 12 deletions(-) + +--- a/drivers/usb/core/message.c ++++ b/drivers/usb/core/message.c +@@ -41,16 +41,17 @@ 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. ++ * Whether or not the wait is killable depends on the flag passed in. ++ * For example, compare usb_bulk_msg() and usb_bulk_msg_killable(). + */ +-static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) ++static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length, ++ bool killable) + { + struct api_context ctx; + unsigned long expire; + int retval; ++ long rc; + + init_completion(&ctx.done); + urb->context = &ctx; +@@ -60,12 +61,21 @@ static int usb_start_wait_urb(struct urb + goto out; + + expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; +- if (!wait_for_completion_timeout(&ctx.done, expire)) { ++ if (killable) ++ rc = wait_for_completion_killable_timeout(&ctx.done, expire); ++ else ++ rc = wait_for_completion_timeout(&ctx.done, expire); ++ if (rc <= 0) { + usb_kill_urb(urb); +- retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status); ++ if (ctx.status != -ENOENT) ++ retval = ctx.status; ++ else if (rc == 0) ++ retval = -ETIMEDOUT; ++ else ++ retval = rc; + + dev_dbg(&urb->dev->dev, +- "%s timed out on ep%d%s len=%u/%u\n", ++ "%s timed out or killed on ep%d%s len=%u/%u\n", + current->comm, + usb_endpoint_num(&urb->ep->desc), + usb_urb_dir_in(urb) ? "in" : "out", +@@ -99,7 +109,7 @@ static int usb_internal_control_msg(stru + usb_fill_control_urb(urb, usb_dev, pipe, (unsigned char *)cmd, data, + len, usb_api_blocking_completion, NULL); + +- retv = usb_start_wait_urb(urb, timeout, &length); ++ retv = usb_start_wait_urb(urb, timeout, &length, false); + if (retv < 0) + return retv; + else +@@ -384,10 +394,59 @@ int usb_bulk_msg(struct usb_device *usb_ + usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, + usb_api_blocking_completion, NULL); + +- return usb_start_wait_urb(urb, timeout, actual_length); ++ return usb_start_wait_urb(urb, timeout, actual_length, false); + } + EXPORT_SYMBOL_GPL(usb_bulk_msg); + ++/** ++ * usb_bulk_msg_killable - Builds a bulk urb, sends it off and waits for completion in a killable state ++ * @usb_dev: pointer to the usb device to send the message to ++ * @pipe: endpoint "pipe" to send the message to ++ * @data: pointer to the data to send ++ * @len: length in bytes of the data to send ++ * @actual_length: pointer to a location to put the actual length transferred ++ * in bytes ++ * @timeout: time in msecs to wait for the message to complete before ++ * timing out (if 0 the wait is forever) ++ * ++ * Context: task context, might sleep. ++ * ++ * This function is just like usb_blk_msg() except that it waits in a ++ * killable state. ++ * ++ * Return: ++ * If successful, 0. Otherwise a negative error number. The number of actual ++ * bytes transferred will be stored in the @actual_length parameter. ++ * ++ */ ++int usb_bulk_msg_killable(struct usb_device *usb_dev, unsigned int pipe, ++ void *data, int len, int *actual_length, int timeout) ++{ ++ struct urb *urb; ++ struct usb_host_endpoint *ep; ++ ++ ep = usb_pipe_endpoint(usb_dev, pipe); ++ if (!ep || len < 0) ++ return -EINVAL; ++ ++ urb = usb_alloc_urb(0, GFP_KERNEL); ++ if (!urb) ++ return -ENOMEM; ++ ++ if ((ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == ++ USB_ENDPOINT_XFER_INT) { ++ pipe = (pipe & ~(3 << 30)) | (PIPE_INTERRUPT << 30); ++ usb_fill_int_urb(urb, usb_dev, pipe, data, len, ++ usb_api_blocking_completion, NULL, ++ ep->desc.bInterval); ++ } else ++ usb_fill_bulk_urb(urb, usb_dev, pipe, data, len, ++ usb_api_blocking_completion, NULL); ++ ++ return usb_start_wait_urb(urb, timeout, actual_length, true); ++} ++EXPORT_SYMBOL_GPL(usb_bulk_msg_killable); ++ + /*-------------------------------------------------------------------*/ + + static void sg_clean(struct usb_sg_request *io) +--- a/include/linux/usb.h ++++ b/include/linux/usb.h +@@ -1811,8 +1811,9 @@ extern int usb_control_msg(struct usb_de + extern int usb_interrupt_msg(struct usb_device *usb_dev, unsigned int pipe, + void *data, int len, int *actual_length, int timeout); + extern int usb_bulk_msg(struct usb_device *usb_dev, unsigned int pipe, +- void *data, int len, int *actual_length, +- int timeout); ++ void *data, int len, int *actual_length, int timeout); ++extern int usb_bulk_msg_killable(struct usb_device *usb_dev, unsigned int pipe, ++ void *data, int len, int *actual_length, int timeout); + + /* wrappers around usb_control_msg() for the most common standard requests */ + int usb_control_msg_send(struct usb_device *dev, __u8 endpoint, __u8 request, diff --git a/queue-5.15/usb-usbtmc-use-usb_bulk_msg_killable-with-user-specified-timeouts.patch b/queue-5.15/usb-usbtmc-use-usb_bulk_msg_killable-with-user-specified-timeouts.patch new file mode 100644 index 0000000000..a113a1bdfa --- /dev/null +++ b/queue-5.15/usb-usbtmc-use-usb_bulk_msg_killable-with-user-specified-timeouts.patch @@ -0,0 +1,57 @@ +From 7784caa413a89487dd14dd5c41db8753483b2acb Mon Sep 17 00:00:00 2001 +From: Alan Stern +Date: Tue, 17 Feb 2026 22:09:22 -0500 +Subject: USB: usbtmc: Use usb_bulk_msg_killable() with user-specified timeouts + +From: Alan Stern + +commit 7784caa413a89487dd14dd5c41db8753483b2acb upstream. + +The usbtmc driver accepts timeout values specified by the user in an +ioctl command, and uses these timeouts for some usb_bulk_msg() calls. +Since the user can specify arbitrarily long timeouts and +usb_bulk_msg() uses unkillable waits, call usb_bulk_msg_killable() +instead to avoid the possibility of the user hanging a kernel thread +indefinitely. + +Reported-by: syzbot+25ba18e2c5040447585d@syzkaller.appspotmail.com +Closes: https://lore.kernel.org/linux-usb/8e1c7ac5-e076-44b0-84b8-1b34b20f0ae1@suse.com/T/#t +Tested-by: syzbot+25ba18e2c5040447585d@syzkaller.appspotmail.com +Signed-off-by: Alan Stern +Fixes: 048c6d88a021 ("usb: usbtmc: Add ioctls to set/get usb timeout") +CC: stable@vger.kernel.org +Link: https://patch.msgid.link/81c6fc24-0607-40f1-8c20-5270dab2fad5@rowland.harvard.edu +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/class/usbtmc.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +--- a/drivers/usb/class/usbtmc.c ++++ b/drivers/usb/class/usbtmc.c +@@ -727,7 +727,7 @@ static int usbtmc488_ioctl_trigger(struc + buffer[1] = data->bTag; + buffer[2] = ~data->bTag; + +- retval = usb_bulk_msg(data->usb_dev, ++ retval = usb_bulk_msg_killable(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, + data->bulk_out), + buffer, USBTMC_HEADER_SIZE, +@@ -1347,7 +1347,7 @@ static int send_request_dev_dep_msg_in(s + buffer[11] = 0; /* Reserved */ + + /* Send bulk URB */ +- retval = usb_bulk_msg(data->usb_dev, ++ retval = usb_bulk_msg_killable(data->usb_dev, + usb_sndbulkpipe(data->usb_dev, + data->bulk_out), + buffer, USBTMC_HEADER_SIZE, +@@ -1419,7 +1419,7 @@ static ssize_t usbtmc_read(struct file * + actual = 0; + + /* Send bulk URB */ +- retval = usb_bulk_msg(data->usb_dev, ++ retval = usb_bulk_msg_killable(data->usb_dev, + usb_rcvbulkpipe(data->usb_dev, + data->bulk_in), + buffer, bufsize, &actual, diff --git a/queue-5.15/usb-xhci-fix-memory-leak-in-xhci_disable_slot.patch b/queue-5.15/usb-xhci-fix-memory-leak-in-xhci_disable_slot.patch new file mode 100644 index 0000000000..a5f5d5c407 --- /dev/null +++ b/queue-5.15/usb-xhci-fix-memory-leak-in-xhci_disable_slot.patch @@ -0,0 +1,66 @@ +From c1c8550e70401159184130a1afc6261db01fc0ce Mon Sep 17 00:00:00 2001 +From: Zilin Guan +Date: Thu, 5 Mar 2026 00:36:37 +0200 +Subject: usb: xhci: Fix memory leak in xhci_disable_slot() + +From: Zilin Guan + +commit c1c8550e70401159184130a1afc6261db01fc0ce upstream. + +xhci_alloc_command() allocates a command structure and, when the +second argument is true, also allocates a completion structure. +Currently, the error handling path in xhci_disable_slot() only frees +the command structure using kfree(), causing the completion structure +to leak. + +Use xhci_free_command() instead of kfree(). xhci_free_command() correctly +frees both the command structure and the associated completion structure. +Since the command structure is allocated with zero-initialization, +command->in_ctx is NULL and will not be erroneously freed by +xhci_free_command(). + +This bug was found using an experimental static analysis tool we are +developing. The tool is based on the LLVM framework and is specifically +designed to detect memory management issues. It is currently under +active development and not yet publicly available, but we plan to +open-source it after our research is published. + +The bug was originally detected on v6.13-rc1 using our static analysis +tool, and we have verified that the issue persists in the latest mainline +kernel. + +We performed build testing on x86_64 with allyesconfig using GCC=11.4.0. +Since triggering these error paths in xhci_disable_slot() requires specific +hardware conditions or abnormal state, we were unable to construct a test +case to reliably trigger these specific error paths at runtime. + +Fixes: 7faac1953ed1 ("xhci: avoid race between disable slot command and host runtime suspend") +CC: stable@vger.kernel.org +Signed-off-by: Zilin Guan +Signed-off-by: Mathias Nyman +Link: https://patch.msgid.link/20260304223639.3882398-2-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/host/xhci.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/host/xhci.c ++++ b/drivers/usb/host/xhci.c +@@ -4056,7 +4056,7 @@ int xhci_disable_slot(struct xhci_hcd *x + if (state == 0xffffffff || (xhci->xhc_state & XHCI_STATE_DYING) || + (xhci->xhc_state & XHCI_STATE_HALTED)) { + spin_unlock_irqrestore(&xhci->lock, flags); +- kfree(command); ++ xhci_free_command(xhci, command); + return -ENODEV; + } + +@@ -4064,7 +4064,7 @@ int xhci_disable_slot(struct xhci_hcd *x + slot_id); + if (ret) { + spin_unlock_irqrestore(&xhci->lock, flags); +- kfree(command); ++ xhci_free_command(xhci, command); + return ret; + } + xhci_ring_cmd_db(xhci); diff --git a/queue-5.15/usb-yurex-fix-race-in-probe.patch b/queue-5.15/usb-yurex-fix-race-in-probe.patch new file mode 100644 index 0000000000..150a704d4f --- /dev/null +++ b/queue-5.15/usb-yurex-fix-race-in-probe.patch @@ -0,0 +1,41 @@ +From 7a875c09899ba0404844abfd8f0d54cdc481c151 Mon Sep 17 00:00:00 2001 +From: Oliver Neukum +Date: Mon, 9 Feb 2026 15:37:20 +0100 +Subject: usb: yurex: fix race in probe + +From: Oliver Neukum + +commit 7a875c09899ba0404844abfd8f0d54cdc481c151 upstream. + +The bbu member of the descriptor must be set to the value +standing for uninitialized values before the URB whose +completion handler sets bbu is submitted. Otherwise there is +a window during which probing can overwrite already retrieved +data. + +Cc: stable +Signed-off-by: Oliver Neukum +Link: https://patch.msgid.link/20260209143720.1507500-1-oneukum@suse.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/misc/yurex.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/usb/misc/yurex.c ++++ b/drivers/usb/misc/yurex.c +@@ -272,6 +272,7 @@ static int yurex_probe(struct usb_interf + dev->int_buffer, YUREX_BUF_SIZE, yurex_interrupt, + dev, 1); + dev->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; ++ dev->bbu = -1; + if (usb_submit_urb(dev->urb, GFP_KERNEL)) { + retval = -EIO; + dev_err(&interface->dev, "Could not submitting URB\n"); +@@ -280,7 +281,6 @@ static int yurex_probe(struct usb_interf + + /* save our data pointer in this interface device */ + usb_set_intfdata(interface, dev); +- dev->bbu = -1; + + /* we can register the device now, as it is ready */ + retval = usb_register_dev(interface, &yurex_class);