Re: Oops tty layer -- 31-rc3 and 31-rc2-git10

From: Alan Cox
Date: Wed Jul 15 2009 - 05:00:26 EST


On Tue, 14 Jul 2009 19:47:02 -0400 (EDT)
Pete Clements <clem@xxxxxxxxxxxxxxxxxxxxx> wrote:

> Fyi:
> Getting the following oops on shutdown with 31-rc2-git10 and 31-rc3.
> (x86 UP)

Yep - testing a fix in -next at the moment.

--


tty: fix close/hangup race

From: Alan Cox <alan@xxxxxxxxxxxxxxx>

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: Alan Cox <alan@xxxxxxxxxxxxxxx>
---

drivers/char/tty_ldisc.c | 25 +++++++++++++++----------
1 files changed, 15 insertions(+), 10 deletions(-)


diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c
index 913aa8d..5018e08 100644
--- a/drivers/char/tty_ldisc.c
+++ b/drivers/char/tty_ldisc.c
@@ -791,17 +791,20 @@ void tty_ldisc_hangup(struct tty_struct *tty)
* N_TTY.
*/
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);
- /* Switch back to N_TTY */
- tty_ldisc_halt(tty);
- tty_ldisc_wait_idle(tty);
- tty_ldisc_reinit(tty);
- /* At this point we have a closed ldisc and we want to
- reopen it. We could defer this to the next open but
- it means auditing a lot of other paths so this is a FIXME */
- WARN_ON(tty_ldisc_open(tty, tty->ldisc));
- tty_ldisc_enable(tty);
+ if (tty->ldisc) { /* Not yet closed */
+ /* Switch back to N_TTY */
+ tty_ldisc_halt(tty);
+ tty_ldisc_wait_idle(tty);
+ tty_ldisc_reinit(tty);
+ /* At this point we have a closed ldisc and we want to
+ reopen it. We could defer this to the next open but
+ it means auditing a lot of other paths so this is
+ a FIXME */
+ WARN_ON(tty_ldisc_open(tty, tty->ldisc));
+ tty_ldisc_enable(tty);
+ }
mutex_unlock(&tty->ldisc_mutex);
tty_reset_termios(tty);
}
@@ -866,6 +869,7 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)

tty_ldisc_wait_idle(tty);

+ mutex_lock(&tty->ldisc_mutex);
/*
* Now kill off the ldisc
*/
@@ -876,6 +880,7 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty)

/* Ensure the next open requests the N_TTY ldisc */
tty_set_termios_ldisc(tty, N_TTY);
+ mutex_unlock(&tty->ldisc_mutex);

/* This will need doing differently if we need to lock */
if (o_tty)
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/