From c8483bc9deff9bf9118aaab2e840b973b75cac3e Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Wed, 5 Nov 2014 12:12:45 -0500 Subject: [PATCH] tty: Invert tty_lock/ldisc_sem lock order Dropping the tty lock to acquire the tty->ldisc_sem allows several race conditions (such as hangup while changing the ldisc) which requires extra states and testing. The ldisc_sem->tty_lock lock order has not been required since tty buffer ownership was moved to tty_port. Reviewed-by: Alan Cox Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/tty_ldisc.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c index 332a622b720..28858ebe291 100644 --- a/drivers/tty/tty_ldisc.c +++ b/drivers/tty/tty_ldisc.c @@ -523,9 +523,11 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (IS_ERR(new_ldisc)) return PTR_ERR(new_ldisc); + tty_lock(tty); retval = tty_ldisc_lock_pair_timeout(tty, o_tty, 5 * HZ); if (retval) { tty_ldisc_put(new_ldisc); + tty_unlock(tty); return retval; } @@ -536,11 +538,11 @@ int tty_set_ldisc(struct tty_struct *tty, int ldisc) if (tty->ldisc->ops->num == ldisc) { tty_ldisc_enable_pair(tty, o_tty); tty_ldisc_put(new_ldisc); + tty_unlock(tty); return 0; } old_ldisc = tty->ldisc; - tty_lock(tty); if (test_bit(TTY_HUPPING, &tty->flags) || test_bit(TTY_HUPPED, &tty->flags)) { @@ -675,8 +677,6 @@ void tty_ldisc_hangup(struct tty_struct *tty) wake_up_interruptible_poll(&tty->write_wait, POLLOUT); wake_up_interruptible_poll(&tty->read_wait, POLLIN); - tty_unlock(tty); - /* * Shutdown the current line discipline, and reset it to * N_TTY if need be. @@ -684,7 +684,6 @@ void tty_ldisc_hangup(struct tty_struct *tty) * Avoid racing set_ldisc or tty_ldisc_release */ tty_ldisc_lock_pair(tty, tty->link); - tty_lock(tty); if (tty->ldisc) { -- 2.46.0