aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_io.c
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2012-07-27 13:02:54 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-27 14:55:59 -0400
commitd155255a344c417acad74156654295a2964e6b81 (patch)
tree71f7c39fda7d71980a64a5e1e35c08cf5c948820 /drivers/tty/tty_io.c
parent373f5aedbc6fb73d30f00eeb0dc7313ecfede908 (diff)
tty: Fix race in tty release
Ian Abbott found that the tty layer would explode with the right set of parallel open and close operations. This is because we race in the handling of tty->drivers->termios[]. Correct this by Making tty_ldisc_release behave like nromal code (takes the lock, does stuff, drops the lock) Drop the tty lock earlier in tty_ldisc_release Taking the tty mutex around the driver->termios update in all cases Adding a WARN_ON to catch future screwups. I also forgot to clean up the pty resources properly. With a pty pair we need to pull both halves out of the tables. Signed-off-by: Alan Cox <alan@linux.intel.com> Tested-by: Ian Abbott <abbotti@mev.co.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r--drivers/tty/tty_io.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index be18d60ddf4c..c6f4d711771b 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1465,7 +1465,6 @@ EXPORT_SYMBOL(tty_free_termios);
1465 * in use. It also gets called when setup of a device fails. 1465 * in use. It also gets called when setup of a device fails.
1466 * 1466 *
1467 * Locking: 1467 * Locking:
1468 * tty_mutex - sometimes only
1469 * takes the file list lock internally when working on the list 1468 * takes the file list lock internally when working on the list
1470 * of ttys that the driver keeps. 1469 * of ttys that the driver keeps.
1471 * 1470 *
@@ -1526,17 +1525,16 @@ EXPORT_SYMBOL(tty_kref_put);
1526 * and decrement the refcount of the backing module. 1525 * and decrement the refcount of the backing module.
1527 * 1526 *
1528 * Locking: 1527 * Locking:
1529 * tty_mutex - sometimes only 1528 * tty_mutex
1530 * takes the file list lock internally when working on the list 1529 * takes the file list lock internally when working on the list
1531 * of ttys that the driver keeps. 1530 * of ttys that the driver keeps.
1532 * FIXME: should we require tty_mutex is held here ??
1533 * 1531 *
1534 */ 1532 */
1535static void release_tty(struct tty_struct *tty, int idx) 1533static void release_tty(struct tty_struct *tty, int idx)
1536{ 1534{
1537 /* This should always be true but check for the moment */ 1535 /* This should always be true but check for the moment */
1538 WARN_ON(tty->index != idx); 1536 WARN_ON(tty->index != idx);
1539 1537 WARN_ON(!mutex_is_locked(&tty_mutex));
1540 if (tty->ops->shutdown) 1538 if (tty->ops->shutdown)
1541 tty->ops->shutdown(tty); 1539 tty->ops->shutdown(tty);
1542 tty_free_termios(tty); 1540 tty_free_termios(tty);
@@ -1708,6 +1706,9 @@ int tty_release(struct inode *inode, struct file *filp)
1708 * The closing flags are now consistent with the open counts on 1706 * The closing flags are now consistent with the open counts on
1709 * both sides, and we've completed the last operation that could 1707 * both sides, and we've completed the last operation that could
1710 * block, so it's safe to proceed with closing. 1708 * block, so it's safe to proceed with closing.
1709 *
1710 * We must *not* drop the tty_mutex until we ensure that a further
1711 * entry into tty_open can not pick up this tty.
1711 */ 1712 */
1712 if (pty_master) { 1713 if (pty_master) {
1713 if (--o_tty->count < 0) { 1714 if (--o_tty->count < 0) {
@@ -1759,12 +1760,13 @@ int tty_release(struct inode *inode, struct file *filp)
1759 } 1760 }
1760 1761
1761 mutex_unlock(&tty_mutex); 1762 mutex_unlock(&tty_mutex);
1763 tty_unlock();
1764 /* At this point the TTY_CLOSING flag should ensure a dead tty
1765 cannot be re-opened by a racing opener */
1762 1766
1763 /* check whether both sides are closing ... */ 1767 /* check whether both sides are closing ... */
1764 if (!tty_closing || (o_tty && !o_tty_closing)) { 1768 if (!tty_closing || (o_tty && !o_tty_closing))
1765 tty_unlock();
1766 return 0; 1769 return 0;
1767 }
1768 1770
1769#ifdef TTY_DEBUG_HANGUP 1771#ifdef TTY_DEBUG_HANGUP
1770 printk(KERN_DEBUG "%s: freeing tty structure...\n", __func__); 1772 printk(KERN_DEBUG "%s: freeing tty structure...\n", __func__);
@@ -1777,12 +1779,14 @@ int tty_release(struct inode *inode, struct file *filp)
1777 * The release_tty function takes care of the details of clearing 1779 * The release_tty function takes care of the details of clearing
1778 * the slots and preserving the termios structure. 1780 * the slots and preserving the termios structure.
1779 */ 1781 */
1782 mutex_lock(&tty_mutex);
1780 release_tty(tty, idx); 1783 release_tty(tty, idx);
1784 mutex_unlock(&tty_mutex);
1781 1785
1782 /* Make this pty number available for reallocation */ 1786 /* Make this pty number available for reallocation */
1783 if (devpts) 1787 if (devpts)
1784 devpts_kill_index(inode, idx); 1788 devpts_kill_index(inode, idx);
1785 tty_unlock(); 1789
1786 return 0; 1790 return 0;
1787} 1791}
1788 1792