From: Greg Kroah-Hartman Date: Tue, 7 Feb 2023 11:08:19 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v5.15.93~22 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e3b1481baa6d0293f50f24096df196a7559c95d2;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: serial-8250_dma-fix-dma-rx-completion-race.patch serial-8250_dma-fix-dma-rx-rearm-race.patch --- diff --git a/queue-4.14/serial-8250_dma-fix-dma-rx-completion-race.patch b/queue-4.14/serial-8250_dma-fix-dma-rx-completion-race.patch new file mode 100644 index 00000000000..93cf6b572a1 --- /dev/null +++ b/queue-4.14/serial-8250_dma-fix-dma-rx-completion-race.patch @@ -0,0 +1,64 @@ +From 31352811e13dc2313f101b890fd4b1ce760b5fe7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= +Date: Mon, 30 Jan 2023 13:48:40 +0200 +Subject: serial: 8250_dma: Fix DMA Rx completion race +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +commit 31352811e13dc2313f101b890fd4b1ce760b5fe7 upstream. + +__dma_rx_complete() is called from two places: + - Through the DMA completion callback dma_rx_complete() + - From serial8250_rx_dma_flush() after IIR_RLSI or IIR_RX_TIMEOUT +The former does not hold port's lock during __dma_rx_complete() which +allows these two to race and potentially insert the same data twice. + +Extend port's lock coverage in dma_rx_complete() to prevent the race +and check if the DMA Rx is still pending completion before calling +into __dma_rx_complete(). + +Reported-by: Gilles BULOZ +Tested-by: Gilles BULOZ +Fixes: 9ee4b83e51f7 ("serial: 8250: Add support for dmaengine") +Cc: stable@vger.kernel.org +Signed-off-by: Ilpo Järvinen +Link: https://lore.kernel.org/r/20230130114841.25749-2-ilpo.jarvinen@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/8250/8250_dma.c | 14 +++++++++++++- + 1 file changed, 13 insertions(+), 1 deletion(-) + +--- a/drivers/tty/serial/8250/8250_dma.c ++++ b/drivers/tty/serial/8250/8250_dma.c +@@ -65,6 +65,18 @@ static void __dma_rx_complete(void *para + tty_flip_buffer_push(tty_port); + } + ++static void dma_rx_complete(void *param) ++{ ++ struct uart_8250_port *p = param; ++ struct uart_8250_dma *dma = p->dma; ++ unsigned long flags; ++ ++ spin_lock_irqsave(&p->port.lock, flags); ++ if (dma->rx_running) ++ __dma_rx_complete(p); ++ spin_unlock_irqrestore(&p->port.lock, flags); ++} ++ + int serial8250_tx_dma(struct uart_8250_port *p) + { + struct uart_8250_dma *dma = p->dma; +@@ -130,7 +142,7 @@ int serial8250_rx_dma(struct uart_8250_p + return -EBUSY; + + dma->rx_running = 1; +- desc->callback = __dma_rx_complete; ++ desc->callback = dma_rx_complete; + desc->callback_param = p; + + dma->rx_cookie = dmaengine_submit(desc); diff --git a/queue-4.14/serial-8250_dma-fix-dma-rx-rearm-race.patch b/queue-4.14/serial-8250_dma-fix-dma-rx-rearm-race.patch new file mode 100644 index 00000000000..91a90072f75 --- /dev/null +++ b/queue-4.14/serial-8250_dma-fix-dma-rx-rearm-race.patch @@ -0,0 +1,88 @@ +From 57e9af7831dcf211c5c689c2a6f209f4abdf0bce Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= +Date: Mon, 30 Jan 2023 13:48:41 +0200 +Subject: serial: 8250_dma: Fix DMA Rx rearm race +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Ilpo Järvinen + +commit 57e9af7831dcf211c5c689c2a6f209f4abdf0bce upstream. + +As DMA Rx can be completed from two places, it is possible that DMA Rx +completes before DMA completion callback had a chance to complete it. +Once the previous DMA Rx has been completed, a new one can be started +on the next UART interrupt. The following race is possible +(uart_unlock_and_check_sysrq_irqrestore() replaced with +spin_unlock_irqrestore() for simplicity/clarity): + +CPU0 CPU1 + dma_rx_complete() +serial8250_handle_irq() + spin_lock_irqsave(&port->lock) + handle_rx_dma() + serial8250_rx_dma_flush() + __dma_rx_complete() + dma->rx_running = 0 + // Complete DMA Rx + spin_unlock_irqrestore(&port->lock) + +serial8250_handle_irq() + spin_lock_irqsave(&port->lock) + handle_rx_dma() + serial8250_rx_dma() + dma->rx_running = 1 + // Setup a new DMA Rx + spin_unlock_irqrestore(&port->lock) + + spin_lock_irqsave(&port->lock) + // sees dma->rx_running = 1 + __dma_rx_complete() + dma->rx_running = 0 + // Incorrectly complete + // running DMA Rx + +This race seems somewhat theoretical to occur for real but handle it +correctly regardless. Check what is the DMA status before complething +anything in __dma_rx_complete(). + +Reported-by: Gilles BULOZ +Tested-by: Gilles BULOZ +Fixes: 9ee4b83e51f7 ("serial: 8250: Add support for dmaengine") +Cc: stable@vger.kernel.org +Signed-off-by: Ilpo Järvinen +Link: https://lore.kernel.org/r/20230130114841.25749-3-ilpo.jarvinen@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/8250/8250_dma.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/drivers/tty/serial/8250/8250_dma.c ++++ b/drivers/tty/serial/8250/8250_dma.c +@@ -52,15 +52,23 @@ static void __dma_rx_complete(void *para + struct uart_8250_dma *dma = p->dma; + struct tty_port *tty_port = &p->port.state->port; + struct dma_tx_state state; ++ enum dma_status dma_status; + int count; + +- dma->rx_running = 0; +- dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); ++ /* ++ * New DMA Rx can be started during the completion handler before it ++ * could acquire port's lock and it might still be ongoing. Don't to ++ * anything in such case. ++ */ ++ dma_status = dmaengine_tx_status(dma->rxchan, dma->rx_cookie, &state); ++ if (dma_status == DMA_IN_PROGRESS) ++ return; + + count = dma->rx_size - state.residue; + + tty_insert_flip_string(tty_port, dma->rx_buf, count); + p->port.icount.rx += count; ++ dma->rx_running = 0; + + tty_flip_buffer_push(tty_port); + } diff --git a/queue-4.14/series b/queue-4.14/series index 165870c57a9..6b549e06b2f 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -21,3 +21,5 @@ parisc-wire-up-ptrace_getregs-ptrace_setregs-for-compat-case.patch mm-hugetlb-proc-check-for-hugetlb-shared-pmd-in-proc-pid-smaps.patch mm-swapfile-add-cond_resched-in-get_swap_pages.patch squashfs-fix-handling-and-sanity-checking-of-xattr_ids-count.patch +serial-8250_dma-fix-dma-rx-completion-race.patch +serial-8250_dma-fix-dma-rx-rearm-race.patch