]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
tty: n_tty: Fix buffer offsets when lookahead is used
authorIlpo Järvinen <ilpo.jarvinen@linux.intel.com>
Tue, 14 May 2024 14:04:29 +0000 (17:04 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 4 Jun 2024 12:07:27 +0000 (14:07 +0200)
When lookahead has "consumed" some characters (la_count > 0),
n_tty_receive_buf_standard() and n_tty_receive_buf_closing() for
characters beyond the la_count are given wrong cp/fp offsets which
leads to duplicating and losing some characters.

If la_count > 0, correct buffer pointers and make count consistent too
(the latter is not strictly necessary to fix the issue but seems more
logical to adjust all variables immediately to keep state consistent).

Reported-by: Vadym Krevs <vkrevs@yahoo.com>
Fixes: 6bb6fa6908eb ("tty: Implement lookahead to process XON/XOFF timely")
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=218834
Tested-by: Vadym Krevs <vkrevs@yahoo.com>
Cc: stable@vger.kernel.org
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Link: https://lore.kernel.org/r/20240514140429.12087-1-ilpo.jarvinen@linux.intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/tty/n_tty.c

index f252d0b5a434ea60e2d38c601e6c3a7de22856f3..5e9ca4376d686e34395958d0e3595aab4df89be2 100644 (file)
@@ -1619,15 +1619,25 @@ static void __receive_buf(struct tty_struct *tty, const u8 *cp, const u8 *fp,
        else if (ldata->raw || (L_EXTPROC(tty) && !preops))
                n_tty_receive_buf_raw(tty, cp, fp, count);
        else if (tty->closing && !L_EXTPROC(tty)) {
-               if (la_count > 0)
+               if (la_count > 0) {
                        n_tty_receive_buf_closing(tty, cp, fp, la_count, true);
-               if (count > la_count)
-                       n_tty_receive_buf_closing(tty, cp, fp, count - la_count, false);
+                       cp += la_count;
+                       if (fp)
+                               fp += la_count;
+                       count -= la_count;
+               }
+               if (count > 0)
+                       n_tty_receive_buf_closing(tty, cp, fp, count, false);
        } else {
-               if (la_count > 0)
+               if (la_count > 0) {
                        n_tty_receive_buf_standard(tty, cp, fp, la_count, true);
-               if (count > la_count)
-                       n_tty_receive_buf_standard(tty, cp, fp, count - la_count, false);
+                       cp += la_count;
+                       if (fp)
+                               fp += la_count;
+                       count -= la_count;
+               }
+               if (count > 0)
+                       n_tty_receive_buf_standard(tty, cp, fp, count, false);
 
                flush_echoes(tty);
                if (tty->ops->flush_chars)