Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

n_tty: signal and flush atomically

When handling signalling char, claim the termios write lock before
signalling waiting readers and writers to prevent further i/o
before flushing the echo and output buffers. This prevents a
userspace signal handler which may output from racing the terminal
flush.

Reference: Bugzilla #99351 ("Output truncated in ssh session after...")
Fixes: commit d2b6f44779d3 ("n_tty: Fix signal handling flushes")
Reported-by: Filipe Brandenburger <filbranden@google.com>
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Peter Hurley and committed by
Greg Kroah-Hartman
3b19e032 52721d9d

+13 -3
+13 -3
drivers/tty/n_tty.c
··· 1108 1108 * Locking: ctrl_lock 1109 1109 */ 1110 1110 1111 - static void isig(int sig, struct tty_struct *tty) 1111 + static void __isig(int sig, struct tty_struct *tty) 1112 1112 { 1113 - struct n_tty_data *ldata = tty->disc_data; 1114 1113 struct pid *tty_pgrp = tty_get_pgrp(tty); 1115 1114 if (tty_pgrp) { 1116 1115 kill_pgrp(tty_pgrp, sig, 1); 1117 1116 put_pid(tty_pgrp); 1118 1117 } 1118 + } 1119 1119 1120 - if (!L_NOFLSH(tty)) { 1120 + static void isig(int sig, struct tty_struct *tty) 1121 + { 1122 + struct n_tty_data *ldata = tty->disc_data; 1123 + 1124 + if (L_NOFLSH(tty)) { 1125 + /* signal only */ 1126 + __isig(sig, tty); 1127 + 1128 + } else { /* signal and flush */ 1121 1129 up_read(&tty->termios_rwsem); 1122 1130 down_write(&tty->termios_rwsem); 1131 + 1132 + __isig(sig, tty); 1123 1133 1124 1134 /* clear echo buffer */ 1125 1135 mutex_lock(&ldata->output_lock);