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

n_tty: Fix echo race

If a tty in N_TTY mode with echo enabled manages to get itself into a state
where
	- echo characters are pending
	- FASYNC is enabled
	- tty_write_wakeup is called from either
		- a device write path (pty)
		- an IRQ (serial)

then it either deadlocks or explodes taking a mutex in the IRQ path.

On the serial side it is almost impossible to reproduce because you have to
go from a full serial port to a near empty one with echo characters
pending. The pty case happens to have become possible to trigger using
emacs and ptys, the pty changes having created a scenario which shows up
this bug.

The code path is

	n_tty:process_echoes() (takes mutex)
	tty_io:tty_put_char()
	pty:pty_write  (or serial paths)
	tty_wakeup     (from pty_write or serial IRQ)
	n_tty_write_wakeup()
	process_echoes()
	*KABOOM*
Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 9237a81a
...@@ -1331,9 +1331,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c) ...@@ -1331,9 +1331,6 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
static void n_tty_write_wakeup(struct tty_struct *tty) static void n_tty_write_wakeup(struct tty_struct *tty)
{ {
/* Write out any echoed characters that are still pending */
process_echoes(tty);
if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) if (tty->fasync && test_and_clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags))
kill_fasync(&tty->fasync, SIGIO, POLL_OUT); kill_fasync(&tty->fasync, SIGIO, POLL_OUT);
} }
......
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