From 26a43ca88eb2ed62cb79987313987d394e844fdd Mon Sep 17 00:00:00 2001 From: Fabrice DJIATSA Date: Tue, 10 Jun 2025 17:01:01 +0200 Subject: [PATCH] drivers: serial: stm32: prevent race condition The async_user_callback could be triggered from both the DMA transfer complete interrupt and a k_work queue timeout. Since the timeout runs outside of an ISR context, it could be interrupted by the DMA ISR. This might leads to a race condition where both paths access and modify shared DMA buffer state (offset and length) simultaneously, causing data corruption or out-of-sequence processing. Introduces proper synchronization to prevent concurrent access to shared DMA buffer variables, ensuring consistent and reliable data handling. Signed-off-by: Fabrice DJIATSA --- drivers/serial/uart_stm32.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index d67513cae8b..0177bcb029f 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -1806,11 +1806,21 @@ static void uart_stm32_async_rx_timeout(struct k_work *work) LOG_DBG("rx timeout"); + /* The DMA is still active and could trigger an interrupt + * while we are processing this timeout, which could cause + * data corruption when the DMA ISR modifies shared data + * as we are operating on it. Prevent data race with ISR by + * masking all interrupts until we're done. + */ + unsigned int key = irq_lock(); + if (data->dma_rx.counter == data->dma_rx.buffer_length) { uart_stm32_async_rx_disable(dev); } else { uart_stm32_dma_rx_flush(dev, STM32_ASYNC_STATUS_TIMEOUT); } + + irq_unlock(key); } static void uart_stm32_async_tx_timeout(struct k_work *work)