From: Greg Kroah-Hartman Date: Mon, 12 Aug 2024 11:46:04 +0000 (+0200) Subject: 6.10-stable patches X-Git-Tag: v6.1.105~68 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=630e0e00db7e257e77d4ce67ac98d8684a08e295;p=thirdparty%2Fkernel%2Fstable-queue.git 6.10-stable patches added patches: memcg-protect-concurrent-access-to-mem_cgroup_idr.patch serial-core-check-uartclk-for-zero-to-avoid-divide-by-zero.patch serial-sc16is7xx-fix-invalid-fifo-access-with-special-register-set.patch serial-sc16is7xx-fix-tx-fifo-corruption.patch tty-vt-conmakehash-cope-with-abs_srctree-no-longer-in-env.patch --- diff --git a/queue-6.10/memcg-protect-concurrent-access-to-mem_cgroup_idr.patch b/queue-6.10/memcg-protect-concurrent-access-to-mem_cgroup_idr.patch new file mode 100644 index 00000000000..060e870edf0 --- /dev/null +++ b/queue-6.10/memcg-protect-concurrent-access-to-mem_cgroup_idr.patch @@ -0,0 +1,104 @@ +From 9972605a238339b85bd16b084eed5f18414d22db Mon Sep 17 00:00:00 2001 +From: Shakeel Butt +Date: Fri, 2 Aug 2024 16:58:22 -0700 +Subject: memcg: protect concurrent access to mem_cgroup_idr + +From: Shakeel Butt + +commit 9972605a238339b85bd16b084eed5f18414d22db upstream. + +Commit 73f576c04b94 ("mm: memcontrol: fix cgroup creation failure after +many small jobs") decoupled the memcg IDs from the CSS ID space to fix the +cgroup creation failures. It introduced IDR to maintain the memcg ID +space. The IDR depends on external synchronization mechanisms for +modifications. For the mem_cgroup_idr, the idr_alloc() and idr_replace() +happen within css callback and thus are protected through cgroup_mutex +from concurrent modifications. However idr_remove() for mem_cgroup_idr +was not protected against concurrency and can be run concurrently for +different memcgs when they hit their refcnt to zero. Fix that. + +We have been seeing list_lru based kernel crashes at a low frequency in +our fleet for a long time. These crashes were in different part of +list_lru code including list_lru_add(), list_lru_del() and reparenting +code. Upon further inspection, it looked like for a given object (dentry +and inode), the super_block's list_lru didn't have list_lru_one for the +memcg of that object. The initial suspicions were either the object is +not allocated through kmem_cache_alloc_lru() or somehow +memcg_list_lru_alloc() failed to allocate list_lru_one() for a memcg but +returned success. No evidence were found for these cases. + +Looking more deeply, we started seeing situations where valid memcg's id +is not present in mem_cgroup_idr and in some cases multiple valid memcgs +have same id and mem_cgroup_idr is pointing to one of them. So, the most +reasonable explanation is that these situations can happen due to race +between multiple idr_remove() calls or race between +idr_alloc()/idr_replace() and idr_remove(). These races are causing +multiple memcgs to acquire the same ID and then offlining of one of them +would cleanup list_lrus on the system for all of them. Later access from +other memcgs to the list_lru cause crashes due to missing list_lru_one. + +Link: https://lkml.kernel.org/r/20240802235822.1830976-1-shakeel.butt@linux.dev +Fixes: 73f576c04b94 ("mm: memcontrol: fix cgroup creation failure after many small jobs") +Signed-off-by: Shakeel Butt +Acked-by: Muchun Song +Reviewed-by: Roman Gushchin +Acked-by: Johannes Weiner +Cc: Michal Hocko +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/memcontrol.c | 22 ++++++++++++++++++++-- + 1 file changed, 20 insertions(+), 2 deletions(-) + +--- a/mm/memcontrol.c ++++ b/mm/memcontrol.c +@@ -5568,11 +5568,28 @@ static struct cftype mem_cgroup_legacy_f + + #define MEM_CGROUP_ID_MAX ((1UL << MEM_CGROUP_ID_SHIFT) - 1) + static DEFINE_IDR(mem_cgroup_idr); ++static DEFINE_SPINLOCK(memcg_idr_lock); ++ ++static int mem_cgroup_alloc_id(void) ++{ ++ int ret; ++ ++ idr_preload(GFP_KERNEL); ++ spin_lock(&memcg_idr_lock); ++ ret = idr_alloc(&mem_cgroup_idr, NULL, 1, MEM_CGROUP_ID_MAX + 1, ++ GFP_NOWAIT); ++ spin_unlock(&memcg_idr_lock); ++ idr_preload_end(); ++ return ret; ++} + + static void mem_cgroup_id_remove(struct mem_cgroup *memcg) + { + if (memcg->id.id > 0) { ++ spin_lock(&memcg_idr_lock); + idr_remove(&mem_cgroup_idr, memcg->id.id); ++ spin_unlock(&memcg_idr_lock); ++ + memcg->id.id = 0; + } + } +@@ -5706,8 +5723,7 @@ static struct mem_cgroup *mem_cgroup_all + if (!memcg) + return ERR_PTR(error); + +- memcg->id.id = idr_alloc(&mem_cgroup_idr, NULL, +- 1, MEM_CGROUP_ID_MAX + 1, GFP_KERNEL); ++ memcg->id.id = mem_cgroup_alloc_id(); + if (memcg->id.id < 0) { + error = memcg->id.id; + goto fail; +@@ -5854,7 +5870,9 @@ static int mem_cgroup_css_online(struct + * publish it here at the end of onlining. This matches the + * regular ID destruction during offlining. + */ ++ spin_lock(&memcg_idr_lock); + idr_replace(&mem_cgroup_idr, memcg, memcg->id.id); ++ spin_unlock(&memcg_idr_lock); + + return 0; + offline_kmem: diff --git a/queue-6.10/serial-core-check-uartclk-for-zero-to-avoid-divide-by-zero.patch b/queue-6.10/serial-core-check-uartclk-for-zero-to-avoid-divide-by-zero.patch new file mode 100644 index 00000000000..81203510367 --- /dev/null +++ b/queue-6.10/serial-core-check-uartclk-for-zero-to-avoid-divide-by-zero.patch @@ -0,0 +1,68 @@ +From 6eabce6608d6f3440f4c03aa3d3ef50a47a3d193 Mon Sep 17 00:00:00 2001 +From: George Kennedy +Date: Wed, 17 Jul 2024 07:24:38 -0500 +Subject: serial: core: check uartclk for zero to avoid divide by zero + +From: George Kennedy + +commit 6eabce6608d6f3440f4c03aa3d3ef50a47a3d193 upstream. + +Calling ioctl TIOCSSERIAL with an invalid baud_base can +result in uartclk being zero, which will result in a +divide by zero error in uart_get_divisor(). The check for +uartclk being zero in uart_set_info() needs to be done +before other settings are made as subsequent calls to +ioctl TIOCSSERIAL for the same port would be impacted if +the uartclk check was done where uartclk gets set. + +Oops: divide error: 0000 PREEMPT SMP KASAN PTI +RIP: 0010:uart_get_divisor (drivers/tty/serial/serial_core.c:580) +Call Trace: + +serial8250_get_divisor (drivers/tty/serial/8250/8250_port.c:2576 + drivers/tty/serial/8250/8250_port.c:2589) +serial8250_do_set_termios (drivers/tty/serial/8250/8250_port.c:502 + drivers/tty/serial/8250/8250_port.c:2741) +serial8250_set_termios (drivers/tty/serial/8250/8250_port.c:2862) +uart_change_line_settings (./include/linux/spinlock.h:376 + ./include/linux/serial_core.h:608 drivers/tty/serial/serial_core.c:222) +uart_port_startup (drivers/tty/serial/serial_core.c:342) +uart_startup (drivers/tty/serial/serial_core.c:368) +uart_set_info (drivers/tty/serial/serial_core.c:1034) +uart_set_info_user (drivers/tty/serial/serial_core.c:1059) +tty_set_serial (drivers/tty/tty_io.c:2637) +tty_ioctl (drivers/tty/tty_io.c:2647 drivers/tty/tty_io.c:2791) +__x64_sys_ioctl (fs/ioctl.c:52 fs/ioctl.c:907 + fs/ioctl.c:893 fs/ioctl.c:893) +do_syscall_64 (arch/x86/entry/common.c:52 + (discriminator 1) arch/x86/entry/common.c:83 (discriminator 1)) +entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130) + +Reported-by: syzkaller +Cc: stable@vger.kernel.org +Signed-off-by: George Kennedy +Rule: add +Link: https://lore.kernel.org/stable/1721148848-9784-1-git-send-email-george.kennedy%40oracle.com +Link: https://lore.kernel.org/r/1721219078-3209-1-git-send-email-george.kennedy@oracle.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/serial_core.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +--- a/drivers/tty/serial/serial_core.c ++++ b/drivers/tty/serial/serial_core.c +@@ -881,6 +881,14 @@ static int uart_set_info(struct tty_stru + new_flags = (__force upf_t)new_info->flags; + old_custom_divisor = uport->custom_divisor; + ++ if (!(uport->flags & UPF_FIXED_PORT)) { ++ unsigned int uartclk = new_info->baud_base * 16; ++ /* check needs to be done here before other settings made */ ++ if (uartclk == 0) { ++ retval = -EINVAL; ++ goto exit; ++ } ++ } + if (!capable(CAP_SYS_ADMIN)) { + retval = -EPERM; + if (change_irq || change_port || diff --git a/queue-6.10/serial-sc16is7xx-fix-invalid-fifo-access-with-special-register-set.patch b/queue-6.10/serial-sc16is7xx-fix-invalid-fifo-access-with-special-register-set.patch new file mode 100644 index 00000000000..44ba36026a2 --- /dev/null +++ b/queue-6.10/serial-sc16is7xx-fix-invalid-fifo-access-with-special-register-set.patch @@ -0,0 +1,57 @@ +From 7d3b793faaab1305994ce568b59d61927235f57b Mon Sep 17 00:00:00 2001 +From: Hugo Villeneuve +Date: Tue, 23 Jul 2024 08:53:01 -0400 +Subject: serial: sc16is7xx: fix invalid FIFO access with special register set + +From: Hugo Villeneuve + +commit 7d3b793faaab1305994ce568b59d61927235f57b upstream. + +When enabling access to the special register set, Receiver time-out and +RHR interrupts can happen. In this case, the IRQ handler will try to read +from the FIFO thru the RHR register at address 0x00, but address 0x00 is +mapped to DLL register, resulting in erroneous FIFO reading. + +Call graph example: + sc16is7xx_startup(): entry + sc16is7xx_ms_proc(): entry + sc16is7xx_set_termios(): entry + sc16is7xx_set_baud(): DLH/DLL = $009C --> access special register set + sc16is7xx_port_irq() entry --> IIR is 0x0C + sc16is7xx_handle_rx() entry + sc16is7xx_fifo_read(): --> unable to access FIFO (RHR) because it is + mapped to DLL (LCR=LCR_CONF_MODE_A) + sc16is7xx_set_baud(): exit --> Restore access to general register set + +Fix the problem by claiming the efr_lock mutex when accessing the Special +register set. + +Fixes: dfeae619d781 ("serial: sc16is7xx") +Cc: stable@vger.kernel.org +Signed-off-by: Hugo Villeneuve +Link: https://lore.kernel.org/r/20240723125302.1305372-3-hugo@hugovil.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/sc16is7xx.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/tty/serial/sc16is7xx.c ++++ b/drivers/tty/serial/sc16is7xx.c +@@ -591,6 +591,8 @@ static int sc16is7xx_set_baud(struct uar + SC16IS7XX_MCR_CLKSEL_BIT, + prescaler == 1 ? 0 : SC16IS7XX_MCR_CLKSEL_BIT); + ++ mutex_lock(&one->efr_lock); ++ + /* Backup LCR and access special register set (DLL/DLH) */ + lcr = sc16is7xx_port_read(port, SC16IS7XX_LCR_REG); + sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, +@@ -605,6 +607,8 @@ static int sc16is7xx_set_baud(struct uar + /* Restore LCR and access to general register set */ + sc16is7xx_port_write(port, SC16IS7XX_LCR_REG, lcr); + ++ mutex_unlock(&one->efr_lock); ++ + return DIV_ROUND_CLOSEST((clk / prescaler) / 16, div); + } + diff --git a/queue-6.10/serial-sc16is7xx-fix-tx-fifo-corruption.patch b/queue-6.10/serial-sc16is7xx-fix-tx-fifo-corruption.patch new file mode 100644 index 00000000000..96dd59aeb17 --- /dev/null +++ b/queue-6.10/serial-sc16is7xx-fix-tx-fifo-corruption.patch @@ -0,0 +1,125 @@ +From 133f4c00b8b2bfcacead9b81e7e8edfceb4b06c4 Mon Sep 17 00:00:00 2001 +From: Hugo Villeneuve +Date: Tue, 23 Jul 2024 08:53:00 -0400 +Subject: serial: sc16is7xx: fix TX fifo corruption + +From: Hugo Villeneuve + +commit 133f4c00b8b2bfcacead9b81e7e8edfceb4b06c4 upstream. + +Sometimes, when a packet is received on channel A at almost the same time +as a packet is about to be transmitted on channel B, we observe with a +logic analyzer that the received packet on channel A is transmitted on +channel B. In other words, the Tx buffer data on channel B is corrupted +with data from channel A. + +The problem appeared since commit 4409df5866b7 ("serial: sc16is7xx: change +EFR lock to operate on each channels"), which changed the EFR locking to +operate on each channel instead of chip-wise. + +This commit has introduced a regression, because the EFR lock is used not +only to protect the EFR registers access, but also, in a very obscure and +undocumented way, to protect access to the data buffer, which is shared by +the Tx and Rx handlers, but also by each channel of the IC. + +Fix this regression first by switching to kfifo_out_linear_ptr() in +sc16is7xx_handle_tx() to eliminate the need for a shared Rx/Tx buffer. + +Secondly, replace the chip-wise Rx buffer with a separate Rx buffer for +each channel. + +Fixes: 4409df5866b7 ("serial: sc16is7xx: change EFR lock to operate on each channels") +Cc: stable@vger.kernel.org +Signed-off-by: Hugo Villeneuve +Link: https://lore.kernel.org/r/20240723125302.1305372-2-hugo@hugovil.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/sc16is7xx.c | 21 +++++++++++---------- + 1 file changed, 11 insertions(+), 10 deletions(-) + +--- a/drivers/tty/serial/sc16is7xx.c ++++ b/drivers/tty/serial/sc16is7xx.c +@@ -326,6 +326,7 @@ struct sc16is7xx_one { + struct kthread_work reg_work; + struct kthread_delayed_work ms_work; + struct sc16is7xx_one_config config; ++ unsigned char buf[SC16IS7XX_FIFO_SIZE]; /* Rx buffer. */ + unsigned int old_mctrl; + u8 old_lcr; /* Value before EFR access. */ + bool irda_mode; +@@ -339,7 +340,6 @@ struct sc16is7xx_port { + unsigned long gpio_valid_mask; + #endif + u8 mctrl_mask; +- unsigned char buf[SC16IS7XX_FIFO_SIZE]; + struct kthread_worker kworker; + struct task_struct *kworker_task; + struct sc16is7xx_one p[]; +@@ -611,18 +611,18 @@ static int sc16is7xx_set_baud(struct uar + static void sc16is7xx_handle_rx(struct uart_port *port, unsigned int rxlen, + unsigned int iir) + { +- struct sc16is7xx_port *s = dev_get_drvdata(port->dev); ++ struct sc16is7xx_one *one = to_sc16is7xx_one(port, port); + unsigned int lsr = 0, bytes_read, i; + bool read_lsr = (iir == SC16IS7XX_IIR_RLSE_SRC) ? true : false; + u8 ch, flag; + +- if (unlikely(rxlen >= sizeof(s->buf))) { ++ if (unlikely(rxlen >= sizeof(one->buf))) { + dev_warn_ratelimited(port->dev, + "ttySC%i: Possible RX FIFO overrun: %d\n", + port->line, rxlen); + port->icount.buf_overrun++; + /* Ensure sanity of RX level */ +- rxlen = sizeof(s->buf); ++ rxlen = sizeof(one->buf); + } + + while (rxlen) { +@@ -635,10 +635,10 @@ static void sc16is7xx_handle_rx(struct u + lsr = 0; + + if (read_lsr) { +- s->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG); ++ one->buf[0] = sc16is7xx_port_read(port, SC16IS7XX_RHR_REG); + bytes_read = 1; + } else { +- sc16is7xx_fifo_read(port, s->buf, rxlen); ++ sc16is7xx_fifo_read(port, one->buf, rxlen); + bytes_read = rxlen; + } + +@@ -671,7 +671,7 @@ static void sc16is7xx_handle_rx(struct u + } + + for (i = 0; i < bytes_read; ++i) { +- ch = s->buf[i]; ++ ch = one->buf[i]; + if (uart_handle_sysrq_char(port, ch)) + continue; + +@@ -689,10 +689,10 @@ static void sc16is7xx_handle_rx(struct u + + static void sc16is7xx_handle_tx(struct uart_port *port) + { +- struct sc16is7xx_port *s = dev_get_drvdata(port->dev); + struct tty_port *tport = &port->state->port; + unsigned long flags; + unsigned int txlen; ++ unsigned char *tail; + + if (unlikely(port->x_char)) { + sc16is7xx_port_write(port, SC16IS7XX_THR_REG, port->x_char); +@@ -717,8 +717,9 @@ static void sc16is7xx_handle_tx(struct u + txlen = 0; + } + +- txlen = uart_fifo_out(port, s->buf, txlen); +- sc16is7xx_fifo_write(port, s->buf, txlen); ++ txlen = kfifo_out_linear_ptr(&tport->xmit_fifo, &tail, txlen); ++ sc16is7xx_fifo_write(port, tail, txlen); ++ uart_xmit_advance(port, txlen); + + uart_port_lock_irqsave(port, &flags); + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) diff --git a/queue-6.10/series b/queue-6.10/series index 9bf6775a371..74833fdf22e 100644 --- a/queue-6.10/series +++ b/queue-6.10/series @@ -206,3 +206,8 @@ tracefs-fix-inode-allocation.patch tracefs-use-generic-inode-rcu-for-synchronizing-freeing.patch ntp-safeguard-against-time_constant-overflow.patch timekeeping-fix-bogus-clock_was_set-invocation-in-do_adjtimex.patch +serial-core-check-uartclk-for-zero-to-avoid-divide-by-zero.patch +serial-sc16is7xx-fix-tx-fifo-corruption.patch +serial-sc16is7xx-fix-invalid-fifo-access-with-special-register-set.patch +tty-vt-conmakehash-cope-with-abs_srctree-no-longer-in-env.patch +memcg-protect-concurrent-access-to-mem_cgroup_idr.patch diff --git a/queue-6.10/tty-vt-conmakehash-cope-with-abs_srctree-no-longer-in-env.patch b/queue-6.10/tty-vt-conmakehash-cope-with-abs_srctree-no-longer-in-env.patch new file mode 100644 index 00000000000..182ea14c043 --- /dev/null +++ b/queue-6.10/tty-vt-conmakehash-cope-with-abs_srctree-no-longer-in-env.patch @@ -0,0 +1,88 @@ +From 6e20753da6bc651e02378a0cdb78f16c42098c88 Mon Sep 17 00:00:00 2001 +From: Max Krummenacher +Date: Thu, 25 Jul 2024 15:20:45 +0200 +Subject: tty: vt: conmakehash: cope with abs_srctree no longer in env + +From: Max Krummenacher + +commit 6e20753da6bc651e02378a0cdb78f16c42098c88 upstream. + +conmakehash uses getenv("abs_srctree") from the environment to strip +the absolute path from the generated sources. +However since commit e2bad142bb3d ("kbuild: unexport abs_srctree and +abs_objtree") this environment variable no longer gets set. +Instead use basename() to indicate the used file in a comment of the +generated source file. + +Fixes: 3bd85c6c97b2 ("tty: vt: conmakehash: Don't mention the full path of the input in output") +Cc: stable +Signed-off-by: Max Krummenacher +Link: https://lore.kernel.org/stable/20240725132056.9151-1-max.oss.09%40gmail.com +Link: https://lore.kernel.org/r/20240725132056.9151-1-max.oss.09@gmail.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/vt/conmakehash.c | 20 +++++++------------- + 1 file changed, 7 insertions(+), 13 deletions(-) + +diff --git a/drivers/tty/vt/conmakehash.c b/drivers/tty/vt/conmakehash.c +index dc2177fec715..82d9db68b2ce 100644 +--- a/drivers/tty/vt/conmakehash.c ++++ b/drivers/tty/vt/conmakehash.c +@@ -11,6 +11,8 @@ + * Copyright (C) 1995-1997 H. Peter Anvin + */ + ++#include ++#include + #include + #include + #include +@@ -76,8 +78,8 @@ static void addpair(int fp, int un) + int main(int argc, char *argv[]) + { + FILE *ctbl; +- const char *tblname, *rel_tblname; +- const char *abs_srctree; ++ const char *tblname; ++ char base_tblname[PATH_MAX]; + char buffer[65536]; + int fontlen; + int i, nuni, nent; +@@ -102,16 +104,6 @@ int main(int argc, char *argv[]) + } + } + +- abs_srctree = getenv("abs_srctree"); +- if (abs_srctree && !strncmp(abs_srctree, tblname, strlen(abs_srctree))) +- { +- rel_tblname = tblname + strlen(abs_srctree); +- while (*rel_tblname == '/') +- ++rel_tblname; +- } +- else +- rel_tblname = tblname; +- + /* For now we assume the default font is always 256 characters. */ + fontlen = 256; + +@@ -253,6 +245,8 @@ int main(int argc, char *argv[]) + for ( i = 0 ; i < fontlen ; i++ ) + nuni += unicount[i]; + ++ strncpy(base_tblname, tblname, PATH_MAX); ++ base_tblname[PATH_MAX - 1] = 0; + printf("\ + /*\n\ + * Do not edit this file; it was automatically generated by\n\ +@@ -264,7 +258,7 @@ int main(int argc, char *argv[]) + #include \n\ + \n\ + u8 dfont_unicount[%d] = \n\ +-{\n\t", rel_tblname, fontlen); ++{\n\t", basename(base_tblname), fontlen); + + for ( i = 0 ; i < fontlen ; i++ ) + { +-- +2.46.0 +