From: Greg Kroah-Hartman Date: Sat, 25 May 2024 15:01:51 +0000 (+0200) Subject: 6.6-stable patches X-Git-Tag: v6.9.3~38 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=5dd48d3a399f07f41bb5e95853a7a6008eac3f03;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches 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 --- 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 index 00000000000..a7de4cc18d1 --- /dev/null +++ b/queue-6.6/input-try-trimming-too-long-modalias-strings.patch @@ -0,0 +1,208 @@ +From 0774d19038c496f0c3602fb505c43e1b2d8eed85 Mon Sep 17 00:00:00 2001 +From: Dmitry Torokhov +Date: Mon, 29 Apr 2024 14:50:41 -0700 +Subject: Input: try trimming too long modalias strings + +From: Dmitry Torokhov + +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 +Reviewed-by: Peter Hutterer +Tested-by: Jason Andryuk +Link: https://lore.kernel.org/r/ZjAWMQCJdrxZkvkB@google.com +Cc: stable@vger.kernel.org +Signed-off-by: Dmitry Torokhov +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..3e6d169b4b7 --- /dev/null +++ b/queue-6.6/serial-8250_bcm7271-use-default_mux_rate-if-possible.patch @@ -0,0 +1,175 @@ +From 614a19b89ca43449196a8af1afac7d55c6781687 Mon Sep 17 00:00:00 2001 +From: Doug Berger +Date: Wed, 24 Apr 2024 15:25:59 -0700 +Subject: serial: 8250_bcm7271: use default_mux_rate if possible + +From: Doug Berger + +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 +Reviewed-by: Florian Fainelli +Tested-by: Florian Fainelli +Link: https://lore.kernel.org/r/20240424222559.1844045-1-opendmb@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..cef8f8f5c0c --- /dev/null +++ b/queue-6.6/serial-8520_mtk-set-rts-on-shutdown-for-rx-in-band-wakeup.patch @@ -0,0 +1,46 @@ +From 4244f830a56058ee0670d80e7ac9fd7c982eb480 Mon Sep 17 00:00:00 2001 +From: Pin-yen Lin +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 + +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 +Signed-off-by: Pin-yen Lin +Link: https://lore.kernel.org/r/20240424130619.2924456-1-treapking@chromium.org +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-6.6/series b/queue-6.6/series index eca4dd30c24..2eb37d87982 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -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 index 00000000000..8e2b2887514 --- /dev/null +++ b/queue-6.6/speakup-fix-sizeof-vs-array_size-bug.patch @@ -0,0 +1,34 @@ +From 008ab3c53bc4f0b2f20013c8f6c204a3203d0b8b Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Mon, 15 Apr 2024 14:02:23 +0300 +Subject: speakup: Fix sizeof() vs ARRAY_SIZE() bug + +From: Dan Carpenter + +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 +Reviewed-by: Samuel Thibault +Link: https://lore.kernel.org/r/d16f67d2-fd0a-4d45-adac-75ddd11001aa@moroto.mountain +Signed-off-by: Greg Kroah-Hartman +--- + 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);