• Linus Torvalds's avatar
    tty: Avoid dropping ldisc_mutex over hangup tty re-initialization · 0b5759c6
    Linus Torvalds authored
    A couple of people have hit the WARN_ON() in drivers/char/tty_io.c,
    tty_open() that is unhappy about seeing the tty line discipline go away
    during the tty hangup. See for example
    
    	http://bugzilla.kernel.org/show_bug.cgi?id=14255
    
    and the reason is that we do the tty_ldisc_halt() outside the
    ldisc_mutex in order to be able to flush the scheduled work without a
    deadlock with vhangup_work.
    
    However, it turns out that we can solve this particular case by
    
     - using "cancel_delayed_work_sync()" in tty_ldisc_halt(), which waits
       for just the particular work, rather than synchronizing with any
       random outstanding pending work.
    
       This won't deadlock, since the buf.work we synchronize with doesn't
       care about the ldisc_mutex, it just flushes the tty ldisc buffers.
    
     - realize that for this particular case, we don't need to wait for any
       hangup work, because we are inside the hangup codepaths ourselves.
    
    so as a result we can just drop the flush_scheduled_work() entirely, and
    then move the tty_ldisc_halt() call to inside the mutex.  That way we
    never expose the partially torn down ldisc state to tty_open(), and hold
    the ldisc_mutex over the whole sequence.
    Reported-by: default avatarIngo Molnar <mingo@elte.hu>
    Reported-by: default avatarHeinz Diehl <htd@fancy-poultry.org>
    Cc: stable@kernel.org
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    0b5759c6
tty_ldisc.c 21 KB