[PATCH] tty: fix lock order inversion in tty_buffer_flush()

Ömer Mete Kaya <[email protected]>
Newsgroups gmane.linux.serial,gmane.linux.kernel
Message-ID <[email protected]>
tty_buffer_flush() calls ld->ops->flush_buffer() while holding
buf->lock. For the N_TTY line discipline, flush_buffer() is
n_tty_flush_buffer(), which acquires termios_rwsem.

However, the documented stable lock order (see tty.h) is:
  termios_rwsem -> buf->lock

Calling flush_buffer() under buf->lock inverts this order and creates
a circular locking dependency detected by lockdep:

  &buf->lock -> console_lock -> &port->mutex -> &tty->termios_rwsem
                                                -> &buf->lock

Fix this by moving the flush_buffer() call outside buf->lock.
The buffer data has already been discarded at this point, so the
ordering change is safe.

Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=d84934b4184d7f9a1aed
Signed-off-by: Ömer Mete Kaya <[email protected]>
---
 drivers/tty/tty_buffer.c | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 96be90db5..bb7b7fbcb 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -244,11 +244,15 @@ void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld)
 	buf->head->read = buf->head->commit;
 	buf->head->lookahead = buf->head->read;
 
-	if (ld && ld->ops->flush_buffer)
-		ld->ops->flush_buffer(tty);
-
 	atomic_dec(&buf->priority);
 	mutex_unlock(&buf->lock);
+	/*
+	 * Call flush_buffer() outside buf->lock: n_tty_flush_buffer()
+	 * acquires termios_rwsem, but the required lock order is
+	 * termios_rwsem -> buf->lock, not the other way around.
+	 */
+	if (ld && ld->ops->flush_buffer)
+		ld->ops->flush_buffer(tty);
 }
 
 /**
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.