Commit c8d50041 authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

tty: fix close/hangup race

We can get a situation where a hangup occurs during or after a close. In
that case the ldisc gets disposed of by the close and the hangup then
explodes.
Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent a3ca86ae
...@@ -790,17 +790,20 @@ void tty_ldisc_hangup(struct tty_struct *tty) ...@@ -790,17 +790,20 @@ void tty_ldisc_hangup(struct tty_struct *tty)
* N_TTY. * N_TTY.
*/ */
if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) {
/* Avoid racing set_ldisc */ /* Avoid racing set_ldisc or tty_ldisc_release */
mutex_lock(&tty->ldisc_mutex); mutex_lock(&tty->ldisc_mutex);
if (tty->ldisc) { /* Not yet closed */
/* Switch back to N_TTY */ /* Switch back to N_TTY */
tty_ldisc_halt(tty); tty_ldisc_halt(tty);
tty_ldisc_wait_idle(tty); tty_ldisc_wait_idle(tty);
tty_ldisc_reinit(tty); tty_ldisc_reinit(tty);
/* At this point we have a closed ldisc and we want to /* At this point we have a closed ldisc and we want to
reopen it. We could defer this to the next open but reopen it. We could defer this to the next open but
it means auditing a lot of other paths so this is a FIXME */ it means auditing a lot of other paths so this is
a FIXME */
WARN_ON(tty_ldisc_open(tty, tty->ldisc)); WARN_ON(tty_ldisc_open(tty, tty->ldisc));
tty_ldisc_enable(tty); tty_ldisc_enable(tty);
}
mutex_unlock(&tty->ldisc_mutex); mutex_unlock(&tty->ldisc_mutex);
tty_reset_termios(tty); tty_reset_termios(tty);
} }
...@@ -865,6 +868,7 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) ...@@ -865,6 +868,7 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
tty_ldisc_wait_idle(tty); tty_ldisc_wait_idle(tty);
mutex_lock(&tty->ldisc_mutex);
/* /*
* Now kill off the ldisc * Now kill off the ldisc
*/ */
...@@ -875,6 +879,7 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) ...@@ -875,6 +879,7 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)
/* Ensure the next open requests the N_TTY ldisc */ /* Ensure the next open requests the N_TTY ldisc */
tty_set_termios_ldisc(tty, N_TTY); tty_set_termios_ldisc(tty, N_TTY);
mutex_unlock(&tty->ldisc_mutex);
/* This will need doing differently if we need to lock */ /* This will need doing differently if we need to lock */
if (o_tty) if (o_tty)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment