This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new 6fdc2dde412 drivers/serial: hold xmit.lock around echo in uart_readv()
6fdc2dde412 is described below

commit 6fdc2dde4121ae8ef9adf2b4d72887b73733797f
Author: yi chen <[email protected]>
AuthorDate: Fri Jul 10 06:12:11 2026 +0800

    drivers/serial: hold xmit.lock around echo in uart_readv()
    
    uart_putxmitchar() manipulates dev->xmit.head/buffer directly with
    no internal locking - every other caller (uart_write()) takes
    dev->xmit.lock first. uart_readv()'s ECHO handling (both the
    backspace/delete erase sequence and the normal character echo)
    calls uart_putxmitchar() without taking that lock, so a concurrent
    uart_write() and a local echo can race on the same circular buffer
    state, corrupting it.
    
    Take dev->xmit.lock around each echo's uart_putxmitchar() calls,
    matching what uart_write() already does. uart_readv() holds
    dev->recv.lock for its own duration, but no other code path ever
    acquires recv.lock while holding xmit.lock, so nesting xmit.lock
    inside the existing recv.lock scope here doesn't introduce a new
    lock-ordering cycle.
    
    Fixes #14845
    
    Signed-off-by: yi chen <[email protected]>
---
 drivers/serial/serial.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/serial/serial.c b/drivers/serial/serial.c
index 5f54d972a98..da80d2e9e66 100644
--- a/drivers/serial/serial.c
+++ b/drivers/serial/serial.c
@@ -1031,9 +1031,11 @@ static ssize_t uart_readv(FAR struct file *filep, FAR 
struct uio *uio)
                   recvd--;
                   if (dev->tc_lflag & ECHO)
                     {
+                      nxmutex_lock(&dev->xmit.lock);
                       uart_putxmitchar(dev, '\b', true);
                       uart_putxmitchar(dev, ' ', true);
                       uart_putxmitchar(dev, '\b', true);
+                      nxmutex_unlock(&dev->xmit.lock);
 
 #ifdef CONFIG_SERIAL_TXDMA
                       uart_dmatxavail(dev);
@@ -1088,12 +1090,14 @@ static ssize_t uart_readv(FAR struct file *filep, FAR 
struct uio *uio)
 
               if (!iscntrl(ch & 0xff) || ch == '\n')
                 {
+                  nxmutex_lock(&dev->xmit.lock);
                   if (ch == '\n')
                     {
                       uart_putxmitchar(dev, '\r', true);
                     }
 
                   uart_putxmitchar(dev, ch, true);
+                  nxmutex_unlock(&dev->xmit.lock);
 
                   /* Mark the tx buffer have echoed content here,
                    * to avoid the tx buffer is empty such as special escape

Reply via email to