All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chengfeng Ye <nicoyip.dev@gmail.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	Jiri Slaby <jirislaby@kernel.org>,
	Johan Hovold <johan@kernel.org>
Cc: linux-kernel@vger.kernel.org, linux-serial@vger.kernel.org,
	Chengfeng Ye <nicoyip.dev@gmail.com>,
	stable@vger.kernel.org
Subject: [PATCH] tty: Serialize saved termios access with device registration
Date: Sun, 27 Sep 2026 02:41:54 +0800	[thread overview]
Message-ID: <20260926184154.3017929-1-nicoyip.dev@gmail.com> (raw)

tty_register_device_attr() frees saved termios data when reusing a minor
number without serializing with tty_init_termios() or tty_save_termios().
The tty_mutex held by the open and close paths does not protect against
this registration-side free.

For example, an n_gsm mux reconfiguration can register a device while its
previous tty is being released. tty_save_termios() loads the saved pointer,
registration clears the array entry and frees the object, and
tty_save_termios() then writes through its stale pointer. The saved-termios
copy in tty_init_termios() is vulnerable to the same lifetime race.

KASAN reported:

  BUG: KASAN: slab-use-after-free in tty_save_termios+0x39a/0x3d0
  Write of size 44 at addr ffff8881012e8180 by task poc/114

  Call Trace:
   tty_save_termios+0x39a/0x3d0
   release_tty+0xb3/0x7a0
   tty_release_struct+0xa0/0xd0
   tty_release+0xc1b/0x11b0
   __fput+0x2f8/0x9e0
   fput_close_sync+0xe2/0x190
   __x64_sys_close+0x78/0xd0

  Allocated by task 110:
   tty_save_termios+0x2c1/0x3d0
   release_tty+0xb3/0x7a0
   tty_release_struct+0xa0/0xd0
   tty_release+0xc1b/0x11b0

  Freed by task 113:
   kfree+0x131/0x3c0
   tty_register_device_attr+0x498/0x8b0
   gsm_activate_mux+0xfb/0x210
   gsmld_ioctl+0x92f/0x14d0
   tty_ioctl+0x915/0x1240
   __x64_sys_ioctl+0x134/0x1c0

Serialize the saved-termios copies and reset with a private mutex. Taking
tty_mutex during registration would invert existing driver lock ordering:
UART registration holds port->mutex, while tty_find_polling_driver() holds
tty_mutex when calling uart_poll_init(), which takes port->mutex. Keep the
new lock confined to the saved-termios operations, with no driver callbacks
inside the critical sections.

Fixes: 93857edd9829 ("tty: reset termios state on device registration")
Cc: stable@vger.kernel.org
Assisted-by: GPT-6-Astra
Signed-off-by: Chengfeng Ye <nicoyip.dev@gmail.com>
---
 drivers/tty/tty_io.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 48569035da56..26bdc4560a4c 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -143,6 +143,7 @@ LIST_HEAD(tty_drivers);			/* linked list of tty drivers */
 
 /* Mutex to protect creating and releasing a tty */
 DEFINE_MUTEX(tty_mutex);
+static DEFINE_MUTEX(tty_termios_mutex);
 
 static ssize_t tty_read(struct kiocb *, struct iov_iter *);
 static ssize_t tty_write(struct kiocb *, struct iov_iter *);
@@ -1219,6 +1220,8 @@ void tty_init_termios(struct tty_struct *tty)
 	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
 		tty->termios = tty->driver->init_termios;
 	else {
+		guard(mutex)(&tty_termios_mutex);
+
 		/* Check for lazy saved data */
 		tp = tty->driver->termios[idx];
 		if (tp != NULL) {
@@ -1441,6 +1444,8 @@ void tty_save_termios(struct tty_struct *tty)
 	if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS)
 		return;
 
+	guard(mutex)(&tty_termios_mutex);
+
 	/* Stash the termios data */
 	tp = tty->driver->termios[idx];
 	if (tp == NULL) {
@@ -3242,10 +3247,12 @@ struct device *tty_register_device_attr(struct tty_driver *driver,
 		 * Free any saved termios data so that the termios state is
 		 * reset when reusing a minor number.
 		 */
-		tp = driver->termios[index];
-		if (tp) {
-			driver->termios[index] = NULL;
-			kfree(tp);
+		scoped_guard(mutex, &tty_termios_mutex) {
+			tp = driver->termios[index];
+			if (tp) {
+				driver->termios[index] = NULL;
+				kfree(tp);
+			}
 		}
 
 		retval = tty_cdev_add(driver, devt, index, 1);
-- 
2.43.0


             reply	other threads:[~2026-09-26 18:42 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-26 18:41 Chengfeng Ye [this message]
2026-09-26 18:52 ` [PATCH] tty: Serialize saved termios access with device registration sashiko-bot
2026-09-30  9:20 ` Johan Hovold
2026-09-30 16:27   ` Chengfeng Ye

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260926184154.3017929-1-nicoyip.dev@gmail.com \
    --to=nicoyip.dev@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=jirislaby@kernel.org \
    --cc=johan@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.