From 42458f41d08f0873299e830464c1232a6839297d Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Thu, 7 Nov 2013 13:59:46 -0500 Subject: n_tty: Ensure reader restarts worker for next reader A departing reader must restart a flush_to_ldisc() worker _before_ the next reader enters the read loop; this is to avoid the new reader concluding no more i/o is available and prematurely exiting, when the old reader simply hasn't re-started the worker yet. Cc: stable # 3.12 Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers/tty/n_tty.c') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 7cdd1eb9406..a2b70c97391 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2243,6 +2243,9 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, if (time) timeout = time; } + n_tty_set_room(tty); + up_read(&tty->termios_rwsem); + mutex_unlock(&ldata->atomic_read_lock); remove_wait_queue(&tty->read_wait, &wait); @@ -2253,8 +2256,6 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, if (b - buf) retval = b - buf; - n_tty_set_room(tty); - up_read(&tty->termios_rwsem); return retval; } -- cgit v1.2.3-70-g09d2 From 6f2225363c205e186c1465c2c7c84f17c1635504 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 8 Nov 2013 09:42:18 -0500 Subject: n_tty: Fix echo overrun tail computation Commit cbfd0340ae1993378fd47179db949e050e16e697, 'n_tty: Process echoes in blocks', introduced an error when consuming the echo buffer tail to prevent buffer overrun, where the incorrect operation code byte is checked to determine how far to advance the tail to the next echo byte. Check the correct byte for the echo operation code byte. Cc: # 3.12.x : c476f65 tty: incorrect test of echo_buf() result for ECHO_OP_START Cc: # 3.12.x Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/tty/n_tty.c') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index a2b70c97391..d8a779d3a61 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -768,7 +768,7 @@ static size_t __process_echoes(struct tty_struct *tty) * data at the tail to prevent a subsequent overrun */ while (ldata->echo_commit - tail >= ECHO_DISCARD_WATERMARK) { if (echo_buf(ldata, tail) == ECHO_OP_START) { - if (echo_buf(ldata, tail) == ECHO_OP_ERASE_TAB) + if (echo_buf(ldata, tail + 1) == ECHO_OP_ERASE_TAB) tail += 3; else tail += 2; -- cgit v1.2.3-70-g09d2 From c77569d2f3ef7844ee4ac7005a57da6898b302a8 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Fri, 22 Nov 2013 07:16:25 -0500 Subject: n_tty: Fix 4096-byte canonical reads Although the maximum allowable canonical line is specified to be 255 bytes (MAX_CANON), the practical limit has actually been the size of the line discipline read buffer (N_TTY_BUF_SIZE == 4096). Commit 32f13521ca68bc624ff6effc77f308a52b038bf0, n_tty: Line copy to user buffer in canonical mode, limited the line copy to 4095 bytes. With a completely full line discipline read buffer and a userspace buffer > 4095, _no_ data was copied, and the read() syscall returned 0, indicating EOF. Fix the interval arithmetic to compute the correct number of bytes to copy to userspace in the range [1..4096]. Cc: # 3.12.x Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/tty/n_tty.c') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index d8a779d3a61..c222a561c5a 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1998,7 +1998,10 @@ static int canon_copy_from_read_buf(struct tty_struct *tty, found = 1; size = N_TTY_BUF_SIZE - tail; - n = (found + eol + size) & (N_TTY_BUF_SIZE - 1); + n = eol - tail; + if (n > 4096) + n += 4096; + n += found; c = n; if (found && read_buf(ldata, eol) == __DISABLED_CHAR) { -- cgit v1.2.3-70-g09d2 From aebf045382edb32bd763d8edea02a559e7dc41e9 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Thu, 7 Nov 2013 14:01:57 -0500 Subject: n_tty: Protect minimum_to_wake reset for concurrent readers With multiple, concurrent readers (each waiting to acquire the atomic_read_lock mutex), a departing reader may mistakenly reset minimum_to_wake after a new reader has already set a new value. Protect the minimum_to_wake reset with the atomic_read_lock critical section. Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- drivers/tty/n_tty.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/tty/n_tty.c') diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index c222a561c5a..0f74945af62 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -2249,12 +2249,12 @@ static ssize_t n_tty_read(struct tty_struct *tty, struct file *file, n_tty_set_room(tty); up_read(&tty->termios_rwsem); - mutex_unlock(&ldata->atomic_read_lock); remove_wait_queue(&tty->read_wait, &wait); - if (!waitqueue_active(&tty->read_wait)) ldata->minimum_to_wake = minimum; + mutex_unlock(&ldata->atomic_read_lock); + __set_current_state(TASK_RUNNING); if (b - buf) retval = b - buf; -- cgit v1.2.3-70-g09d2