--- /dev/null
+From 966031f340185eddd05affcf72b740549f056348 Mon Sep 17 00:00:00 2001
+From: Linus Torvalds <torvalds@linux-foundation.org>
+Date: Wed, 20 Dec 2017 17:57:06 -0800
+Subject: n_tty: fix EXTPROC vs ICANON interaction with TIOCINQ (aka FIONREAD)
+
+From: Linus Torvalds <torvalds@linux-foundation.org>
+
+commit 966031f340185eddd05affcf72b740549f056348 upstream.
+
+We added support for EXTPROC back in 2010 in commit 26df6d13406d ("tty:
+Add EXTPROC support for LINEMODE") and the intent was to allow it to
+override some (all?) ICANON behavior. Quoting from that original commit
+message:
+
+ There is a new bit in the termios local flag word, EXTPROC.
+ When this bit is set, several aspects of the terminal driver
+ are disabled. Input line editing, character echo, and mapping
+ of signals are all disabled. This allows the telnetd to turn
+ off these functions when in linemode, but still keep track of
+ what state the user wants the terminal to be in.
+
+but the problem turns out that "several aspects of the terminal driver
+are disabled" is a bit ambiguous, and you can really confuse the n_tty
+layer by setting EXTPROC and then causing some of the ICANON invariants
+to no longer be maintained.
+
+This fixes at least one such case (TIOCINQ) becoming unhappy because of
+the confusion over whether ICANON really means ICANON when EXTPROC is set.
+
+This basically makes TIOCINQ match the case of read: if EXTPROC is set,
+we ignore ICANON. Also, make sure to reset the ICANON state ie EXTPROC
+changes, not just if ICANON changes.
+
+Fixes: 26df6d13406d ("tty: Add EXTPROC support for LINEMODE")
+Reported-by: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
+Reported-by: syzkaller <syzkaller@googlegroups.com>
+Cc: Jiri Slaby <jslaby@suse.com>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/tty/n_tty.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/tty/n_tty.c
++++ b/drivers/tty/n_tty.c
+@@ -1801,7 +1801,7 @@ static void n_tty_set_termios(struct tty
+ {
+ struct n_tty_data *ldata = tty->disc_data;
+
+- if (!old || (old->c_lflag ^ tty->termios.c_lflag) & ICANON) {
++ if (!old || (old->c_lflag ^ tty->termios.c_lflag) & (ICANON | EXTPROC)) {
+ bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
+ ldata->line_start = ldata->read_tail;
+ if (!L_ICANON(tty) || !read_cnt(ldata)) {
+@@ -2493,7 +2493,7 @@ static int n_tty_ioctl(struct tty_struct
+ return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
+ case TIOCINQ:
+ down_write(&tty->termios_rwsem);
+- if (L_ICANON(tty))
++ if (L_ICANON(tty) && !L_EXTPROC(tty))
+ retval = inq_canon(ldata);
+ else
+ retval = read_cnt(ldata);