Messages in this thread Patch in this message |  | | From | Cen Zhang <> | | Subject | [PATCH] tty: n_tty: read termios under lock in poll | | Date | Sun, 10 May 2026 10:59:40 +0800 |
| |
n_tty_poll() uses input_available_p() to decide whether buffered input makes the tty readable. That helper reads termios state through L_EXTPROC(), VMIN, and VTIME, but the poll path does not hold the read side of tty->termios_rwsem.
tty_set_termios() updates tty->termios under the write side of the same semaphore, including c_lflag and c_cc[]. n_tty_read() already takes the read side before reading the same termios fields and before calling input_available_p(). Protect the poll-side readiness checks the same way so poll observes a coherent termios state when deciding whether to report readable input.
Do not hold termios_rwsem across tty_buffer_flush_work(), matching the read path which drops the semaphore before flushing pending receive work and then checks input availability again after reacquiring it.
Signed-off-by: Cen Zhang <zzzccc427@gmail.com> --- drivers/tty/n_tty.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index e6a0f5b40d0a..c8e1882782db 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2437,13 +2437,17 @@ static __poll_t n_tty_poll(struct tty_struct *tty, struct file *file, poll_wait(file, &tty->read_wait, wait); poll_wait(file, &tty->write_wait, wait); - if (input_available_p(tty, 1)) - mask |= EPOLLIN | EPOLLRDNORM; - else { - tty_buffer_flush_work(tty->port); + scoped_guard(rwsem_read, &tty->termios_rwsem) { if (input_available_p(tty, 1)) mask |= EPOLLIN | EPOLLRDNORM; } + if (!(mask & (EPOLLIN | EPOLLRDNORM))) { + tty_buffer_flush_work(tty->port); + scoped_guard(rwsem_read, &tty->termios_rwsem) { + if (input_available_p(tty, 1)) + mask |= EPOLLIN | EPOLLRDNORM; + } + } if (tty->ctrl.packet && tty->link->ctrl.pktstatus) mask |= EPOLLPRI | EPOLLIN | EPOLLRDNORM; if (test_bit(TTY_OTHER_CLOSED, &tty->flags)) -- 2.43.0
|  |