Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tty: pty: Fix race condition between release_one_tty and pty_write

Especially when a linked tty is used such as pty, the linked tty
port's buf works have not been cancelled while master tty port's
buf work has been cancelled. Since release_one_tty and flush_to_ldisc
run in workqueue threads separately, when pty_cleanup happens and
link tty port is freed, flush_to_ldisc tries to access freed port
and port->itty, eventually it causes a panic.
This patch utilizes the magic value with holding the tty_mutex to
check if the tty->link is valid.

Fixes: 2b022ab7542d ("pty: cancel pty slave port buf's work in tty_release")
Signed-off-by: Sahara <keun-o.park@darkmatter.ae>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Sahara and committed by
Greg Kroah-Hartman
b9ca5f85 75ddbc1f

+10
+7
drivers/tty/pty.c
··· 116 116 if (tty->stopped) 117 117 return 0; 118 118 119 + mutex_lock(&tty_mutex); 120 + if (to->magic != TTY_MAGIC) { 121 + mutex_unlock(&tty_mutex); 122 + return -EIO; 123 + } 124 + 119 125 if (c > 0) { 120 126 spin_lock_irqsave(&to->port->lock, flags); 121 127 /* Stuff the data into the input queue of the other end */ ··· 131 125 tty_flip_buffer_push(to->port); 132 126 spin_unlock_irqrestore(&to->port->lock, flags); 133 127 } 128 + mutex_unlock(&tty_mutex); 134 129 return c; 135 130 } 136 131
+3
drivers/tty/tty_io.c
··· 1448 1448 struct tty_driver *driver = tty->driver; 1449 1449 struct module *owner = driver->owner; 1450 1450 1451 + mutex_lock(&tty_mutex); 1451 1452 if (tty->ops->cleanup) 1452 1453 tty->ops->cleanup(tty); 1453 1454 1454 1455 tty->magic = 0; 1456 + mutex_unlock(&tty_mutex); 1457 + 1455 1458 tty_driver_kref_put(driver); 1456 1459 module_put(owner); 1457 1460