• Daniel Gibson's avatar
    tty: n_tty: Restore EOF push handling behavior · 65a8b287
    Daniel Gibson authored
    TTYs in ICANON mode have a special case that allows "pushing" a line
    without a regular EOL character (like newline), by using EOF (the EOT
    character - ASCII 0x4) as a pseudo-EOL. It is silently discarded, so
    the reader of the PTS will receive the line *without* EOF or any other
    terminating character.
    
    This special case has an edge case: What happens if the readers buffer
    is the same size as the line (without EOF)? Will they be able to tell
    if the whole line is received, i.e. if the next read() will return more
    of the same line or the next line?
    
    There are two possibilities,  that both have (dis)advantages:
    
    1. The next read() returns 0. FreeBSD (13.0) and OSX (10.11) do this.
       Advantage: The reader can interpret this as "the line is over".
       Disadvantage: read() returning 0 means EOF, the reader could also
       interpret it as "there's no more data" and stop reading or even
       close the PT.
    
    2. The next read() returns the next line, the EOF is silently discarded.
       Solaris (or at least OpenIndiana 2021.10) does this, Linux has done
       do this since commit 40d5e090 ("n_tty: Fix EOF push handling");
       this behavior was recently broken by commit 35930307 ("tty:
       n_tty: do not look ahead for EOL character past the end of the buffer").
       Advantage: read() won't return 0 (EOF), reader less likely to be
       confused (and things like `while(read(..)>0)` don't break)
       Disadvantage: The reader can't really know if the read() continues
       the last line (that filled the whole read buffer) or starts a
       new line.
    
    As both options are defensible (and are used by other Unix-likes), it's
    best to stick to the "old" behavior since "n_tty: Fix EOF push handling"
    of 2013, i.e. silently discard that EOF.
    
    This patch - that I actually got from Linus for testing and only
    modified slightly - restores that behavior by skipping an EOF
    character if it's the next character after reading is done.
    
    Based on a patch from Linus Torvalds.
    
    Link: https://bugzilla.kernel.org/show_bug.cgi?id=215611
    Fixes: 35930307 ("tty: n_tty: do not look ahead for EOL character past the end of the buffer")
    Cc: Peter Hurley <peter@hurleysoftware.com>
    Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    Cc: Jiri Slaby <jirislaby@kernel.org>
    Reviewed-and-tested-by: default avatarDaniel Gibson <daniel@gibson.sh>
    Acked-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: default avatarDaniel Gibson <daniel@gibson.sh>
    Link: https://lore.kernel.org/r/20220329235810.452513-2-daniel@gibson.shSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    65a8b287
n_tty.c 62 KB