• Peter Hurley's avatar
    tty: Destroy ldisc instance on hangup · 892d1fa7
    Peter Hurley authored
    Currently, when the tty is hungup, the ldisc is re-instanced; ie., the
    current instance is destroyed and a new instance is created. The purpose
    of this design was to guarantee a valid, open ldisc for the lifetime of
    the tty.
    
    However, now that tty buffers are owned by and have lifetime equivalent
    to the tty_port (since v3.10), any data received immediately after the
    ldisc is re-instanced may cause continued driver i/o operations
    concurrently with the driver's hangup() operation. For drivers that
    shutdown h/w on hangup, this is unexpected and usually bad. For example,
    the serial core may free the xmit buffer page concurrently with an
    in-progress write() operation (triggered by echo).
    
    With the existing stable and robust ldisc reference handling, the
    cleaned-up tty_reopen(), the straggling unsafe ldisc use cleaned up, and
    the preparation to properly handle a NULL tty->ldisc, the ldisc instance
    can be destroyed and only re-instanced when the tty is re-opened.
    
    If the tty was opened as /dev/console or /dev/tty0, the original behavior
    of re-instancing the ldisc is retained (the 'reinit' parameter to
    tty_ldisc_hangup() is true). This is required since those file descriptors
    are never hungup.
    
    This patch has neglible impact on userspace; the tty file_operations ptr
    is changed to point to the hungup file operations _before_ the ldisc
    instance is destroyed, so only racing file operations might now retrieve
    a NULL ldisc reference (which is simply handled as if the hungup file
    operation had been called instead -- see "tty: Prepare for destroying
    line discipline on hangup").
    
    This resolves a long-standing FIXME and several crash reports.
    Signed-off-by: default avatarPeter Hurley <peter@hurleysoftware.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    892d1fa7
tty_ldisc.c 19.4 KB