]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 25 May 2024 15:01:51 +0000 (17:01 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 25 May 2024 15:01:51 +0000 (17:01 +0200)
added patches:
input-try-trimming-too-long-modalias-strings.patch
serial-8250_bcm7271-use-default_mux_rate-if-possible.patch
serial-8520_mtk-set-rts-on-shutdown-for-rx-in-band-wakeup.patch
speakup-fix-sizeof-vs-array_size-bug.patch

queue-6.6/input-try-trimming-too-long-modalias-strings.patch [new file with mode: 0644]
queue-6.6/serial-8250_bcm7271-use-default_mux_rate-if-possible.patch [new file with mode: 0644]
queue-6.6/serial-8520_mtk-set-rts-on-shutdown-for-rx-in-band-wakeup.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/speakup-fix-sizeof-vs-array_size-bug.patch [new file with mode: 0644]

diff --git a/queue-6.6/input-try-trimming-too-long-modalias-strings.patch b/queue-6.6/input-try-trimming-too-long-modalias-strings.patch
new file mode 100644 (file)
index 0000000..a7de4cc
--- /dev/null
@@ -0,0 +1,208 @@
+From 0774d19038c496f0c3602fb505c43e1b2d8eed85 Mon Sep 17 00:00:00 2001
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Date: Mon, 29 Apr 2024 14:50:41 -0700
+Subject: Input: try trimming too long modalias strings
+
+From: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+
+commit 0774d19038c496f0c3602fb505c43e1b2d8eed85 upstream.
+
+If an input device declares too many capability bits then modalias
+string for such device may become too long and not fit into uevent
+buffer, resulting in failure of sending said uevent. This, in turn,
+may prevent userspace from recognizing existence of such devices.
+
+This is typically not a concern for real hardware devices as they have
+limited number of keys, but happen with synthetic devices such as
+ones created by xen-kbdfront driver, which creates devices as being
+capable of delivering all possible keys, since it doesn't know what
+keys the backend may produce.
+
+To deal with such devices input core will attempt to trim key data,
+in the hope that the rest of modalias string will fit in the given
+buffer. When trimming key data it will indicate that it is not
+complete by placing "+," sign, resulting in conversions like this:
+
+old: k71,72,73,74,78,7A,7B,7C,7D,8E,9E,A4,AD,E0,E1,E4,F8,174,
+new: k71,72,73,74,78,7A,7B,7C,+,
+
+This should allow existing udev rules continue to work with existing
+devices, and will also allow writing more complex rules that would
+recognize trimmed modalias and check input device characteristics by
+other means (for example by parsing KEY= data in uevent or parsing
+input device sysfs attributes).
+
+Note that the driver core may try adding more uevent environment
+variables once input core is done adding its own, so when forming
+modalias we can not use the entire available buffer, so we reduce
+it by somewhat an arbitrary amount (96 bytes).
+
+Reported-by: Jason Andryuk <jandryuk@gmail.com>
+Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
+Tested-by: Jason Andryuk <jandryuk@gmail.com>
+Link: https://lore.kernel.org/r/ZjAWMQCJdrxZkvkB@google.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/input/input.c |  104 ++++++++++++++++++++++++++++++++++++++++++--------
+ 1 file changed, 89 insertions(+), 15 deletions(-)
+
+--- a/drivers/input/input.c
++++ b/drivers/input/input.c
+@@ -1378,19 +1378,19 @@ static int input_print_modalias_bits(cha
+                                    char name, const unsigned long *bm,
+                                    unsigned int min_bit, unsigned int max_bit)
+ {
+-      int len = 0, i;
++      int bit = min_bit;
++      int len = 0;
+       len += snprintf(buf, max(size, 0), "%c", name);
+-      for (i = min_bit; i < max_bit; i++)
+-              if (bm[BIT_WORD(i)] & BIT_MASK(i))
+-                      len += snprintf(buf + len, max(size - len, 0), "%X,", i);
++      for_each_set_bit_from(bit, bm, max_bit)
++              len += snprintf(buf + len, max(size - len, 0), "%X,", bit);
+       return len;
+ }
+-static int input_print_modalias(char *buf, int size, const struct input_dev *id,
+-                              int add_cr)
++static int input_print_modalias_parts(char *buf, int size, int full_len,
++                                    const struct input_dev *id)
+ {
+-      int len;
++      int len, klen, remainder, space;
+       len = snprintf(buf, max(size, 0),
+                      "input:b%04Xv%04Xp%04Xe%04X-",
+@@ -1399,8 +1399,48 @@ static int input_print_modalias(char *bu
+       len += input_print_modalias_bits(buf + len, size - len,
+                               'e', id->evbit, 0, EV_MAX);
+-      len += input_print_modalias_bits(buf + len, size - len,
++
++      /*
++       * Calculate the remaining space in the buffer making sure we
++       * have place for the terminating 0.
++       */
++      space = max(size - (len + 1), 0);
++
++      klen = input_print_modalias_bits(buf + len, size - len,
+                               'k', id->keybit, KEY_MIN_INTERESTING, KEY_MAX);
++      len += klen;
++
++      /*
++       * If we have more data than we can fit in the buffer, check
++       * if we can trim key data to fit in the rest. We will indicate
++       * that key data is incomplete by adding "+" sign at the end, like
++       * this: * "k1,2,3,45,+,".
++       *
++       * Note that we shortest key info (if present) is "k+," so we
++       * can only try to trim if key data is longer than that.
++       */
++      if (full_len && size < full_len + 1 && klen > 3) {
++              remainder = full_len - len;
++              /*
++               * We can only trim if we have space for the remainder
++               * and also for at least "k+," which is 3 more characters.
++               */
++              if (remainder <= space - 3) {
++                      /*
++                       * We are guaranteed to have 'k' in the buffer, so
++                       * we need at least 3 additional bytes for storing
++                       * "+," in addition to the remainder.
++                       */
++                      for (int i = size - 1 - remainder - 3; i >= 0; i--) {
++                              if (buf[i] == 'k' || buf[i] == ',') {
++                                      strcpy(buf + i + 1, "+,");
++                                      len = i + 3; /* Not counting '\0' */
++                                      break;
++                              }
++                      }
++              }
++      }
++
+       len += input_print_modalias_bits(buf + len, size - len,
+                               'r', id->relbit, 0, REL_MAX);
+       len += input_print_modalias_bits(buf + len, size - len,
+@@ -1416,12 +1456,25 @@ static int input_print_modalias(char *bu
+       len += input_print_modalias_bits(buf + len, size - len,
+                               'w', id->swbit, 0, SW_MAX);
+-      if (add_cr)
+-              len += snprintf(buf + len, max(size - len, 0), "\n");
+-
+       return len;
+ }
++static int input_print_modalias(char *buf, int size, const struct input_dev *id)
++{
++      int full_len;
++
++      /*
++       * Printing is done in 2 passes: first one figures out total length
++       * needed for the modalias string, second one will try to trim key
++       * data in case when buffer is too small for the entire modalias.
++       * If the buffer is too small regardless, it will fill as much as it
++       * can (without trimming key data) into the buffer and leave it to
++       * the caller to figure out what to do with the result.
++       */
++      full_len = input_print_modalias_parts(NULL, 0, 0, id);
++      return input_print_modalias_parts(buf, size, full_len, id);
++}
++
+ static ssize_t input_dev_show_modalias(struct device *dev,
+                                      struct device_attribute *attr,
+                                      char *buf)
+@@ -1429,7 +1482,9 @@ static ssize_t input_dev_show_modalias(s
+       struct input_dev *id = to_input_dev(dev);
+       ssize_t len;
+-      len = input_print_modalias(buf, PAGE_SIZE, id, 1);
++      len = input_print_modalias(buf, PAGE_SIZE, id);
++      if (len < PAGE_SIZE - 2)
++              len += snprintf(buf + len, PAGE_SIZE - len, "\n");
+       return min_t(int, len, PAGE_SIZE);
+ }
+@@ -1641,6 +1696,23 @@ static int input_add_uevent_bm_var(struc
+       return 0;
+ }
++/*
++ * This is a pretty gross hack. When building uevent data the driver core
++ * may try adding more environment variables to kobj_uevent_env without
++ * telling us, so we have no idea how much of the buffer we can use to
++ * avoid overflows/-ENOMEM elsewhere. To work around this let's artificially
++ * reduce amount of memory we will use for the modalias environment variable.
++ *
++ * The potential additions are:
++ *
++ * SEQNUM=18446744073709551615 - (%llu - 28 bytes)
++ * HOME=/ (6 bytes)
++ * PATH=/sbin:/bin:/usr/sbin:/usr/bin (34 bytes)
++ *
++ * 68 bytes total. Allow extra buffer - 96 bytes
++ */
++#define UEVENT_ENV_EXTRA_LEN  96
++
+ static int input_add_uevent_modalias_var(struct kobj_uevent_env *env,
+                                        const struct input_dev *dev)
+ {
+@@ -1650,9 +1722,11 @@ static int input_add_uevent_modalias_var
+               return -ENOMEM;
+       len = input_print_modalias(&env->buf[env->buflen - 1],
+-                                 sizeof(env->buf) - env->buflen,
+-                                 dev, 0);
+-      if (len >= (sizeof(env->buf) - env->buflen))
++                                 (int)sizeof(env->buf) - env->buflen -
++                                      UEVENT_ENV_EXTRA_LEN,
++                                 dev);
++      if (len >= ((int)sizeof(env->buf) - env->buflen -
++                                      UEVENT_ENV_EXTRA_LEN))
+               return -ENOMEM;
+       env->buflen += len;
diff --git a/queue-6.6/serial-8250_bcm7271-use-default_mux_rate-if-possible.patch b/queue-6.6/serial-8250_bcm7271-use-default_mux_rate-if-possible.patch
new file mode 100644 (file)
index 0000000..3e6d169
--- /dev/null
@@ -0,0 +1,175 @@
+From 614a19b89ca43449196a8af1afac7d55c6781687 Mon Sep 17 00:00:00 2001
+From: Doug Berger <opendmb@gmail.com>
+Date: Wed, 24 Apr 2024 15:25:59 -0700
+Subject: serial: 8250_bcm7271: use default_mux_rate if possible
+
+From: Doug Berger <opendmb@gmail.com>
+
+commit 614a19b89ca43449196a8af1afac7d55c6781687 upstream.
+
+There is a scenario when resuming from some power saving states
+with no_console_suspend where console output can be generated
+before the 8250_bcm7271 driver gets the opportunity to restore
+the baud_mux_clk frequency. Since the baud_mux_clk is at its
+default frequency at this time the output can be garbled until
+the driver gets the opportunity to resume.
+
+Since this is only an issue with console use of the serial port
+during that window and the console isn't likely to use baud
+rates that require alternate baud_mux_clk frequencies, allow the
+driver to select the default_mux_rate if it is accurate enough.
+
+Fixes: 41a469482de2 ("serial: 8250: Add new 8250-core based Broadcom STB driver")
+Cc: stable@vger.kernel.org
+Signed-off-by: Doug Berger <opendmb@gmail.com>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://lore.kernel.org/r/20240424222559.1844045-1-opendmb@gmail.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/8250/8250_bcm7271.c |  101 +++++++++++++++++++--------------
+ 1 file changed, 60 insertions(+), 41 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_bcm7271.c
++++ b/drivers/tty/serial/8250/8250_bcm7271.c
+@@ -676,18 +676,46 @@ static void init_real_clk_rates(struct d
+       clk_set_rate(priv->baud_mux_clk, priv->default_mux_rate);
+ }
++static u32 find_quot(struct device *dev, u32 freq, u32 baud, u32 *percent)
++{
++      u32 quot;
++      u32 rate;
++      u64 hires_rate;
++      u64 hires_baud;
++      u64 hires_err;
++
++      rate = freq / 16;
++      quot = DIV_ROUND_CLOSEST(rate, baud);
++      if (!quot)
++              return 0;
++
++      /* increase resolution to get xx.xx percent */
++      hires_rate = div_u64((u64)rate * 10000, (u64)quot);
++      hires_baud = (u64)baud * 10000;
++
++      /* get the delta */
++      if (hires_rate > hires_baud)
++              hires_err = (hires_rate - hires_baud);
++      else
++              hires_err = (hires_baud - hires_rate);
++
++      *percent = (unsigned long)DIV_ROUND_CLOSEST_ULL(hires_err, baud);
++
++      dev_dbg(dev, "Baud rate: %u, MUX Clk: %u, Error: %u.%u%%\n",
++              baud, freq, *percent / 100, *percent % 100);
++
++      return quot;
++}
++
+ static void set_clock_mux(struct uart_port *up, struct brcmuart_priv *priv,
+                       u32 baud)
+ {
+       u32 percent;
+       u32 best_percent = UINT_MAX;
+       u32 quot;
++      u32 freq;
+       u32 best_quot = 1;
+-      u32 rate;
+-      int best_index = -1;
+-      u64 hires_rate;
+-      u64 hires_baud;
+-      u64 hires_err;
++      u32 best_freq = 0;
+       int rc;
+       int i;
+       int real_baud;
+@@ -696,44 +724,35 @@ static void set_clock_mux(struct uart_po
+       if (priv->baud_mux_clk == NULL)
+               return;
+-      /* Find the closest match for specified baud */
+-      for (i = 0; i < ARRAY_SIZE(priv->real_rates); i++) {
+-              if (priv->real_rates[i] == 0)
+-                      continue;
+-              rate = priv->real_rates[i] / 16;
+-              quot = DIV_ROUND_CLOSEST(rate, baud);
+-              if (!quot)
+-                      continue;
+-
+-              /* increase resolution to get xx.xx percent */
+-              hires_rate = (u64)rate * 10000;
+-              hires_baud = (u64)baud * 10000;
+-
+-              hires_err = div_u64(hires_rate, (u64)quot);
+-
+-              /* get the delta */
+-              if (hires_err > hires_baud)
+-                      hires_err = (hires_err - hires_baud);
+-              else
+-                      hires_err = (hires_baud - hires_err);
+-
+-              percent = (unsigned long)DIV_ROUND_CLOSEST_ULL(hires_err, baud);
+-              dev_dbg(up->dev,
+-                      "Baud rate: %u, MUX Clk: %u, Error: %u.%u%%\n",
+-                      baud, priv->real_rates[i], percent / 100,
+-                      percent % 100);
+-              if (percent < best_percent) {
+-                      best_percent = percent;
+-                      best_index = i;
+-                      best_quot = quot;
++      /* Try default_mux_rate first */
++      quot = find_quot(up->dev, priv->default_mux_rate, baud, &percent);
++      if (quot) {
++              best_percent = percent;
++              best_freq = priv->default_mux_rate;
++              best_quot = quot;
++      }
++      /* If more than 1% error, find the closest match for specified baud */
++      if (best_percent > 100) {
++              for (i = 0; i < ARRAY_SIZE(priv->real_rates); i++) {
++                      freq = priv->real_rates[i];
++                      if (freq == 0 || freq == priv->default_mux_rate)
++                              continue;
++                      quot = find_quot(up->dev, freq, baud, &percent);
++                      if (!quot)
++                              continue;
++
++                      if (percent < best_percent) {
++                              best_percent = percent;
++                              best_freq = freq;
++                              best_quot = quot;
++                      }
+               }
+       }
+-      if (best_index == -1) {
++      if (!best_freq) {
+               dev_err(up->dev, "Error, %d BAUD rate is too fast.\n", baud);
+               return;
+       }
+-      rate = priv->real_rates[best_index];
+-      rc = clk_set_rate(priv->baud_mux_clk, rate);
++      rc = clk_set_rate(priv->baud_mux_clk, best_freq);
+       if (rc)
+               dev_err(up->dev, "Error selecting BAUD MUX clock\n");
+@@ -742,8 +761,8 @@ static void set_clock_mux(struct uart_po
+               dev_err(up->dev, "Error, baud: %d has %u.%u%% error\n",
+                       baud, percent / 100, percent % 100);
+-      real_baud = rate / 16 / best_quot;
+-      dev_dbg(up->dev, "Selecting BAUD MUX rate: %u\n", rate);
++      real_baud = best_freq / 16 / best_quot;
++      dev_dbg(up->dev, "Selecting BAUD MUX rate: %u\n", best_freq);
+       dev_dbg(up->dev, "Requested baud: %u, Actual baud: %u\n",
+               baud, real_baud);
+@@ -752,7 +771,7 @@ static void set_clock_mux(struct uart_po
+       i += (i / 2);
+       priv->char_wait = ns_to_ktime(i);
+-      up->uartclk = rate;
++      up->uartclk = best_freq;
+ }
+ static void brcmstb_set_termios(struct uart_port *up,
diff --git a/queue-6.6/serial-8520_mtk-set-rts-on-shutdown-for-rx-in-band-wakeup.patch b/queue-6.6/serial-8520_mtk-set-rts-on-shutdown-for-rx-in-band-wakeup.patch
new file mode 100644 (file)
index 0000000..cef8f8f
--- /dev/null
@@ -0,0 +1,46 @@
+From 4244f830a56058ee0670d80e7ac9fd7c982eb480 Mon Sep 17 00:00:00 2001
+From: Pin-yen Lin <treapking@chromium.org>
+Date: Wed, 24 Apr 2024 20:58:08 +0800
+Subject: serial: 8520_mtk: Set RTS on shutdown for Rx in-band wakeup
+
+From: Pin-yen Lin <treapking@chromium.org>
+
+commit 4244f830a56058ee0670d80e7ac9fd7c982eb480 upstream.
+
+When Rx in-band wakeup is enabled, set RTS to true in mtk8250_shutdown()
+so the connected device can still send message and trigger IRQ when the
+system is suspended.
+
+Fixes: 18c9d4a3c249 ("serial: When UART is suspended, set RTS to false")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Pin-yen Lin <treapking@chromium.org>
+Link: https://lore.kernel.org/r/20240424130619.2924456-1-treapking@chromium.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/8250/8250_mtk.c |    8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250_mtk.c
++++ b/drivers/tty/serial/8250/8250_mtk.c
+@@ -209,15 +209,19 @@ static int mtk8250_startup(struct uart_p
+ static void mtk8250_shutdown(struct uart_port *port)
+ {
+-#ifdef CONFIG_SERIAL_8250_DMA
+       struct uart_8250_port *up = up_to_u8250p(port);
+       struct mtk8250_data *data = port->private_data;
++      int irq = data->rx_wakeup_irq;
++#ifdef CONFIG_SERIAL_8250_DMA
+       if (up->dma)
+               data->rx_status = DMA_RX_SHUTDOWN;
+ #endif
+-      return serial8250_do_shutdown(port);
++      serial8250_do_shutdown(port);
++
++      if (irq >= 0)
++              serial8250_do_set_mctrl(&up->port, TIOCM_RTS);
+ }
+ static void mtk8250_disable_intrs(struct uart_8250_port *up, int mask)
index eca4dd30c24b8717828c4d5f829c35ee81e56288..2eb37d879827b0c9555ff60b80204c37ff2f2fd9 100644 (file)
@@ -1,2 +1,6 @@
 tty-n_gsm-fix-possible-out-of-bounds-in-gsm0_receive.patch
 tty-n_gsm-fix-missing-receive-state-reset-after-mode-switch.patch
+speakup-fix-sizeof-vs-array_size-bug.patch
+serial-8250_bcm7271-use-default_mux_rate-if-possible.patch
+serial-8520_mtk-set-rts-on-shutdown-for-rx-in-band-wakeup.patch
+input-try-trimming-too-long-modalias-strings.patch
diff --git a/queue-6.6/speakup-fix-sizeof-vs-array_size-bug.patch b/queue-6.6/speakup-fix-sizeof-vs-array_size-bug.patch
new file mode 100644 (file)
index 0000000..8e2b288
--- /dev/null
@@ -0,0 +1,34 @@
+From 008ab3c53bc4f0b2f20013c8f6c204a3203d0b8b Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@linaro.org>
+Date: Mon, 15 Apr 2024 14:02:23 +0300
+Subject: speakup: Fix sizeof() vs ARRAY_SIZE() bug
+
+From: Dan Carpenter <dan.carpenter@linaro.org>
+
+commit 008ab3c53bc4f0b2f20013c8f6c204a3203d0b8b upstream.
+
+The "buf" pointer is an array of u16 values.  This code should be
+using ARRAY_SIZE() (which is 256) instead of sizeof() (which is 512),
+otherwise it can the still got out of bounds.
+
+Fixes: c8d2f34ea96e ("speakup: Avoid crash on very long word")
+Cc: stable@vger.kernel.org
+Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
+Reviewed-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
+Link: https://lore.kernel.org/r/d16f67d2-fd0a-4d45-adac-75ddd11001aa@moroto.mountain
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/accessibility/speakup/main.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/accessibility/speakup/main.c
++++ b/drivers/accessibility/speakup/main.c
+@@ -574,7 +574,7 @@ static u_long get_word(struct vc_data *v
+       }
+       attr_ch = get_char(vc, (u_short *)tmp_pos, &spk_attr);
+       buf[cnt++] = attr_ch;
+-      while (tmpx < vc->vc_cols - 1 && cnt < sizeof(buf) - 1) {
++      while (tmpx < vc->vc_cols - 1 && cnt < ARRAY_SIZE(buf) - 1) {
+               tmp_pos += 2;
+               tmpx++;
+               ch = get_char(vc, (u_short *)tmp_pos, &temp);