aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_ldisc.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_ldisc.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_ldisc.c')
-rw-r--r--drivers/tty/tty_ldisc.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
index e6156c60d190..3d0687197d09 100644
--- a/drivers/tty/tty_ldisc.c
+++ b/drivers/tty/tty_ldisc.c
@@ -912,7 +912,6 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
912 * race with the set_ldisc code path. 912 * race with the set_ldisc code path.
913 */ 913 */
914 914
915 tty_unlock();
916 tty_ldisc_halt(tty); 915 tty_ldisc_halt(tty);
917 tty_ldisc_flush_works(tty); 916 tty_ldisc_flush_works(tty);
918 tty_lock(); 917 tty_lock();
@@ -930,6 +929,8 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
930 tty_set_termios_ldisc(tty, N_TTY); 929 tty_set_termios_ldisc(tty, N_TTY);
931 mutex_unlock(&tty->ldisc_mutex); 930 mutex_unlock(&tty->ldisc_mutex);
932 931
932 tty_unlock();
933
933 /* This will need doing differently if we need to lock */ 934 /* This will need doing differently if we need to lock */
934 if (o_tty) 935 if (o_tty)
935 tty_ldisc_release(o_tty, NULL); 936 tty_ldisc_release(o_tty, NULL);