]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 21 Sep 2025 17:33:32 +0000 (19:33 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 21 Sep 2025 17:33:32 +0000 (19:33 +0200)
added patches:
serial-sc16is7xx-fix-bug-in-flow-control-levels-init.patch
usb-gadget-dummy-hcd-fix-locking-bug-in-rt-enabled-kernels.patch
usb-gadget-dummy_hcd-remove-usage-of-list-iterator-past-the-loop-body.patch

queue-5.4/serial-sc16is7xx-fix-bug-in-flow-control-levels-init.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/usb-gadget-dummy-hcd-fix-locking-bug-in-rt-enabled-kernels.patch [new file with mode: 0644]
queue-5.4/usb-gadget-dummy_hcd-remove-usage-of-list-iterator-past-the-loop-body.patch [new file with mode: 0644]

diff --git a/queue-5.4/serial-sc16is7xx-fix-bug-in-flow-control-levels-init.patch b/queue-5.4/serial-sc16is7xx-fix-bug-in-flow-control-levels-init.patch
new file mode 100644 (file)
index 0000000..63c0cbb
--- /dev/null
@@ -0,0 +1,88 @@
+From sashal@kernel.org Wed Sep 17 15:03:27 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Sep 2025 09:03:19 -0400
+Subject: serial: sc16is7xx: fix bug in flow control levels init
+To: stable@vger.kernel.org
+Cc: Hugo Villeneuve <hvilleneuve@dimonoff.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20250917130319.535006-1-sashal@kernel.org>
+
+From: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+
+[ Upstream commit 535fd4c98452c87537a40610abba45daf5761ec6 ]
+
+When trying to set MCR[2], XON1 is incorrectly accessed instead. And when
+writing to the TCR register to configure flow control levels, we are
+incorrectly writing to the MSR register. The default value of $00 is then
+used for TCR, which means that selectable trigger levels in FCR are used
+in place of TCR.
+
+TCR/TLR access requires EFR[4] (enable enhanced functions) and MCR[2]
+to be set. EFR[4] is already set in probe().
+
+MCR access requires LCR[7] to be zero.
+
+Since LCR is set to $BF when trying to set MCR[2], XON1 is incorrectly
+accessed instead because MCR shares the same address space as XON1.
+
+Since MCR[2] is unmodified and still zero, when writing to TCR we are in
+fact writing to MSR because TCR/TLR registers share the same address space
+as MSR/SPR.
+
+Fix by first removing useless reconfiguration of EFR[4] (enable enhanced
+functions), as it is already enabled in sc16is7xx_probe() since commit
+43c51bb573aa ("sc16is7xx: make sure device is in suspend once probed").
+Now LCR is $00, which means that MCR access is enabled.
+
+Also remove regcache_cache_bypass() calls since we no longer access the
+enhanced registers set, and TCR is already declared as volatile (in fact
+by declaring MSR as volatile, which shares the same address).
+
+Finally disable access to TCR/TLR registers after modifying them by
+clearing MCR[2].
+
+Note: the comment about "... and internal clock div" is wrong and can be
+      ignored/removed as access to internal clock div registers (DLL/DLH)
+      is permitted only when LCR[7] is logic 1, not when enhanced features
+      is enabled. And DLL/DLH access is not needed in sc16is7xx_startup().
+
+Fixes: dfeae619d781 ("serial: sc16is7xx")
+Cc: stable@vger.kernel.org
+Signed-off-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
+Link: https://lore.kernel.org/r/20250731124451.1108864-1-hugo@hugovil.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+[ s->regmap renames + context ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/sc16is7xx.c |   13 ++-----------
+ 1 file changed, 2 insertions(+), 11 deletions(-)
+
+--- a/drivers/tty/serial/sc16is7xx.c
++++ b/drivers/tty/serial/sc16is7xx.c
+@@ -1032,16 +1032,6 @@ static int sc16is7xx_startup(struct uart
+       sc16is7xx_port_write(port, SC16IS7XX_FCR_REG,
+                            SC16IS7XX_FCR_FIFO_BIT);
+-      /* Enable EFR */
+-      sc16is7xx_port_write(port, SC16IS7XX_LCR_REG,
+-                           SC16IS7XX_LCR_CONF_MODE_B);
+-
+-      regcache_cache_bypass(s->regmap, true);
+-
+-      /* Enable write access to enhanced features and internal clock div */
+-      sc16is7xx_port_write(port, SC16IS7XX_EFR_REG,
+-                           SC16IS7XX_EFR_ENABLE_BIT);
+-
+       /* Enable TCR/TLR */
+       sc16is7xx_port_update(port, SC16IS7XX_MCR_REG,
+                             SC16IS7XX_MCR_TCRTLR_BIT,
+@@ -1053,7 +1043,8 @@ static int sc16is7xx_startup(struct uart
+                            SC16IS7XX_TCR_RX_RESUME(24) |
+                            SC16IS7XX_TCR_RX_HALT(48));
+-      regcache_cache_bypass(s->regmap, false);
++      /* Disable TCR/TLR access */
++      sc16is7xx_port_update(port, SC16IS7XX_MCR_REG, SC16IS7XX_MCR_TCRTLR_BIT, 0);
+       /* Now, initialize the UART */
+       sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, SC16IS7XX_LCR_WORD_LEN_8);
index 33f8c31f90aee07c562e46477a176087f77937c1..fc6d083712483b6e51fdf7f0d3960e6b9a2eb7b1 100644 (file)
@@ -46,3 +46,6 @@ rds-ib-increment-i_fastreg_wrs-before-bailing-out.patch
 asoc-wm8940-correct-typo-in-control-name.patch
 asoc-wm8974-correct-pll-rate-rounding.patch
 asoc-sof-intel-hda-stream-fix-incorrect-variable-use.patch
+usb-gadget-dummy_hcd-remove-usage-of-list-iterator-past-the-loop-body.patch
+usb-gadget-dummy-hcd-fix-locking-bug-in-rt-enabled-kernels.patch
+serial-sc16is7xx-fix-bug-in-flow-control-levels-init.patch
diff --git a/queue-5.4/usb-gadget-dummy-hcd-fix-locking-bug-in-rt-enabled-kernels.patch b/queue-5.4/usb-gadget-dummy-hcd-fix-locking-bug-in-rt-enabled-kernels.patch
new file mode 100644 (file)
index 0000000..2642954
--- /dev/null
@@ -0,0 +1,95 @@
+From sashal@kernel.org Wed Sep 17 15:30:07 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Sep 2025 09:30:03 -0400
+Subject: USB: gadget: dummy-hcd: Fix locking bug in RT-enabled kernels
+To: stable@vger.kernel.org
+Cc: Alan Stern <stern@rowland.harvard.edu>, stable <stable@kernel.org>, Yunseong Kim <ysk@kzalloc.com>, syzbot+8baacc4139f12fa77909@syzkaller.appspotmail.com, Sebastian Andrzej Siewior <bigeasy@linutronix.de>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20250917133003.551232-2-sashal@kernel.org>
+
+From: Alan Stern <stern@rowland.harvard.edu>
+
+[ Upstream commit 8d63c83d8eb922f6c316320f50c82fa88d099bea ]
+
+Yunseong Kim and the syzbot fuzzer both reported a problem in
+RT-enabled kernels caused by the way dummy-hcd mixes interrupt
+management and spin-locking.  The pattern was:
+
+       local_irq_save(flags);
+       spin_lock(&dum->lock);
+       ...
+       spin_unlock(&dum->lock);
+       ...             // calls usb_gadget_giveback_request()
+       local_irq_restore(flags);
+
+The code was written this way because usb_gadget_giveback_request()
+needs to be called with interrupts disabled and the private lock not
+held.
+
+While this pattern works fine in non-RT kernels, it's not good when RT
+is enabled.  RT kernels handle spinlocks much like mutexes; in particular,
+spin_lock() may sleep.  But sleeping is not allowed while local
+interrupts are disabled.
+
+To fix the problem, rewrite the code to conform to the pattern used
+elsewhere in dummy-hcd and other UDC drivers:
+
+       spin_lock_irqsave(&dum->lock, flags);
+       ...
+       spin_unlock(&dum->lock);
+       usb_gadget_giveback_request(...);
+       spin_lock(&dum->lock);
+       ...
+       spin_unlock_irqrestore(&dum->lock, flags);
+
+This approach satisfies the RT requirements.
+
+Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
+Cc: stable <stable@kernel.org>
+Fixes: b4dbda1a22d2 ("USB: dummy-hcd: disable interrupts during req->complete")
+Reported-by: Yunseong Kim <ysk@kzalloc.com>
+Closes: <https://lore.kernel.org/linux-usb/5b337389-73b9-4ee4-a83e-7e82bf5af87a@kzalloc.com/>
+Reported-by: syzbot+8baacc4139f12fa77909@syzkaller.appspotmail.com
+Closes: <https://lore.kernel.org/linux-usb/68ac2411.050a0220.37038e.0087.GAE@google.com/>
+Tested-by: syzbot+8baacc4139f12fa77909@syzkaller.appspotmail.com
+CC: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+CC: stable@vger.kernel.org
+Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Link: https://lore.kernel.org/r/bb192ae2-4eee-48ee-981f-3efdbbd0d8f0@rowland.harvard.edu
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/udc/dummy_hcd.c |    8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -758,8 +758,7 @@ static int dummy_dequeue(struct usb_ep *
+       if (!dum->driver)
+               return -ESHUTDOWN;
+-      local_irq_save(flags);
+-      spin_lock(&dum->lock);
++      spin_lock_irqsave(&dum->lock, flags);
+       list_for_each_entry(iter, &ep->queue, queue) {
+               if (&iter->req != _req)
+                       continue;
+@@ -769,15 +768,16 @@ static int dummy_dequeue(struct usb_ep *
+               retval = 0;
+               break;
+       }
+-      spin_unlock(&dum->lock);
+       if (retval == 0) {
+               dev_dbg(udc_dev(dum),
+                               "dequeued req %p from %s, len %d buf %p\n",
+                               req, _ep->name, _req->length, _req->buf);
++              spin_unlock(&dum->lock);
+               usb_gadget_giveback_request(_ep, _req);
++              spin_lock(&dum->lock);
+       }
+-      local_irq_restore(flags);
++      spin_unlock_irqrestore(&dum->lock, flags);
+       return retval;
+ }
diff --git a/queue-5.4/usb-gadget-dummy_hcd-remove-usage-of-list-iterator-past-the-loop-body.patch b/queue-5.4/usb-gadget-dummy_hcd-remove-usage-of-list-iterator-past-the-loop-body.patch
new file mode 100644 (file)
index 0000000..e91e291
--- /dev/null
@@ -0,0 +1,63 @@
+From sashal@kernel.org Wed Sep 17 15:30:06 2025
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 17 Sep 2025 09:30:02 -0400
+Subject: usb: gadget: dummy_hcd: remove usage of list iterator past the loop body
+To: stable@vger.kernel.org
+Cc: Jakob Koschel <jakobkoschel@gmail.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20250917133003.551232-1-sashal@kernel.org>
+
+From: Jakob Koschel <jakobkoschel@gmail.com>
+
+[ Upstream commit 7975f080d3557725160a878b1a64339043ba3d91 ]
+
+To move the list iterator variable into the list_for_each_entry_*()
+macro in the future it should be avoided to use the list iterator
+variable after the loop body.
+
+To *never* use the list iterator variable after the loop it was
+concluded to use a separate iterator variable [1].
+
+Link: https://lore.kernel.org/all/YhdfEIwI4EdtHdym@kroah.com/
+Signed-off-by: Jakob Koschel <jakobkoschel@gmail.com>
+Link: https://lore.kernel.org/r/20220308171818.384491-26-jakobkoschel@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 8d63c83d8eb9 ("USB: gadget: dummy-hcd: Fix locking bug in RT-enabled kernels")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/gadget/udc/dummy_hcd.c |   17 +++++++++--------
+ 1 file changed, 9 insertions(+), 8 deletions(-)
+
+--- a/drivers/usb/gadget/udc/dummy_hcd.c
++++ b/drivers/usb/gadget/udc/dummy_hcd.c
+@@ -748,7 +748,7 @@ static int dummy_dequeue(struct usb_ep *
+       struct dummy            *dum;
+       int                     retval = -EINVAL;
+       unsigned long           flags;
+-      struct dummy_request    *req = NULL;
++      struct dummy_request    *req = NULL, *iter;
+       if (!_ep || !_req)
+               return retval;
+@@ -760,13 +760,14 @@ static int dummy_dequeue(struct usb_ep *
+       local_irq_save(flags);
+       spin_lock(&dum->lock);
+-      list_for_each_entry(req, &ep->queue, queue) {
+-              if (&req->req == _req) {
+-                      list_del_init(&req->queue);
+-                      _req->status = -ECONNRESET;
+-                      retval = 0;
+-                      break;
+-              }
++      list_for_each_entry(iter, &ep->queue, queue) {
++              if (&iter->req != _req)
++                      continue;
++              list_del_init(&iter->queue);
++              _req->status = -ECONNRESET;
++              req = iter;
++              retval = 0;
++              break;
+       }
+       spin_unlock(&dum->lock);