APPLIED: [Trusty][pull request] (upstream) n_tty: Fix buffer overruns with larger-than-4k pastes

Brad Figg brad.figg at canonical.com
Fri Jul 25 14:46:12 UTC 2014


-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 07/24/2014 01:43 PM, Rafael David Tinoco wrote:
> From 0b8b060c8932c600a240fb1fa055fa103b5e969a Mon Sep 17 00:00:00 2001
> From: Peter Hurley <peter at hurleysoftware.com>
> Date: Tue, 10 Dec 2013 17:12:02 -0500
> Subject: n_tty: Fix buffer overruns  with larger-than-4k pastes
> 
> BugLink: http://bugs.launchpad.net/bugs/1208740
> 
> n_tty: Fix buffer overruns with larger-than-4k pastes
> 
> readline() inadvertently triggers an error recovery path when
> pastes larger than 4k overrun the line discipline buffer. The
> error recovery path discards input when the line discipline buffer
> is full and operating in canonical mode and no newline has been
> received. Because readline() changes the termios to non-canonical
> mode to read the line char-by-char, the line discipline buffer
> can become full, and then when readline() restores termios back
> to canonical mode for the caller, the now-full line discipline
> buffer triggers the error recovery.
> 
> When changing termios from non-canon to canon mode and the read
> buffer contains data, simulate an EOF push _without_ the
> DISABLED_CHAR in the read buffer.
> 
> Importantly for the readline() problem, the termios can be
> changed back to non-canonical mode without changes to the read
> buffer occurring; ie., as if the previous termios change had not
> happened (as long as no intervening read took place).
> 
> Preserve existing userspace behavior which allows '\0's already
> received in non-canon mode to be read as '\0's in canon mode
> (rather than trigger add'l EOF pushes or an actual EOF).
> 
> Patch based on original proposal and discussion here
> https://bugzilla.kernel.org/show_bug.cgi?id=55991
> by Stas Sergeev <stsp at users.sourceforge.net>
> 
> OriginalAuthor: Peter Hurley <peter at hurleysoftware.com>
> Reported-by: Margarita Manterola <margamanterola at gmail.com>
> Acked-by: Stas Sergeev <stsp at users.sourceforge.net>
> Signed-off-by: Peter Hurley <peter at hurleysoftware.com>
> (cherry-picked from commit 4d0ed18277cc6f07513ee0b04475f19cd69e75ef v3.14-rc1)
> Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
> Signed-off-by: Rafael David Tinoco <rafael.tinoco at canonical.com>
> ---
>  drivers/tty/n_tty.c | 26 +++++++++++++++++++++++---
>  1 file changed, 23 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
> index 86093e2..f591184 100644
> --- a/drivers/tty/n_tty.c
> +++ b/drivers/tty/n_tty.c
> @@ -105,6 +105,7 @@ struct n_tty_data {
>  
>  	/* must hold exclusive termios_rwsem to reset these */
>  	unsigned char lnext:1, erasing:1, raw:1, real_raw:1, icanon:1;
> +	unsigned char push:1;
>  
>  	/* shared by producer and consumer */
>  	char read_buf[N_TTY_BUF_SIZE];
> @@ -342,6 +343,7 @@ static void reset_buffer_flags(struct n_tty_data *ldata)
>  
>  	ldata->erasing = 0;
>  	bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
> +	ldata->push = 0;
>  }
>  
>  static void n_tty_packet_mode_flush(struct tty_struct *tty)
> @@ -1762,7 +1764,16 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
>  
>  	if (!old || (old->c_lflag ^ tty->termios.c_lflag) & ICANON) {
>  		bitmap_zero(ldata->read_flags, N_TTY_BUF_SIZE);
> -		ldata->line_start = ldata->canon_head = ldata->read_tail;
> +		ldata->line_start = ldata->read_tail;
> +		if (!L_ICANON(tty) || !read_cnt(ldata)) {
> +			ldata->canon_head = ldata->read_tail;
> +			ldata->push = 0;
> +		} else {
> +			set_bit((ldata->read_head - 1) & (N_TTY_BUF_SIZE - 1),
> +				ldata->read_flags);
> +			ldata->canon_head = ldata->read_head;
> +			ldata->push = 1;
> +		}
>  		ldata->erasing = 0;
>  		ldata->lnext = 0;
>  	}
> @@ -1967,6 +1978,12 @@ static int copy_from_read_buf(struct tty_struct *tty,
>   *	it copies one line of input up to and including the line-delimiting
>   *	character into the user-space buffer.
>   *
> + *	NB: When termios is changed from non-canonical to canonical mode and
> + *	the read buffer contains data, n_tty_set_termios() simulates an EOF
> + *	push (as if C-d were input) _without_ the DISABLED_CHAR in the buffer.
> + *	This causes data already processed as input to be immediately available
> + *	as input although a newline has not been received.
> + *
>   *	Called under the atomic_read_lock mutex
>   *
>   *	n_tty_read()/consumer path:
> @@ -2013,7 +2030,7 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
>  	n += found;
>  	c = n;
>  
> -	if (found && read_buf(ldata, eol) == __DISABLED_CHAR) {
> +	if (found && !ldata->push && read_buf(ldata, eol) == __DISABLED_CHAR) {
>  		n--;
>  		eof_push = !n && ldata->read_tail != ldata->line_start;
>  	}
> @@ -2040,7 +2057,10 @@ static int canon_copy_from_read_buf(struct tty_struct *tty,
>  	ldata->read_tail += c;
>  
>  	if (found) {
> -		ldata->line_start = ldata->read_tail;
> +		if (!ldata->push)
> +			ldata->line_start = ldata->read_tail;
> +		else
> +			ldata->push = 0;
>  		tty_audit_push(tty);
>  	}
>  	return eof_push ? -EAGAIN : 0;
> 
> 
> 


- -- 
Brad Figg brad.figg at canonical.com http://www.canonical.com
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iQIcBAEBAgAGBQJT0m2sAAoJEAx7WJsQW+f3TxYQAIZVxLQsVeBuDIsjRWgzSoLt
WYGIjgC7erWhbziJ54jwZUEGqGoUBIwYMlMV0M7ty0B/J0tbH9VaACkM/MjOwoYZ
AhKgZot4GarmZTlelb8hAoq0nNIa25L2P0fKzHU3Rfd2DWJ/ck7el1+YMPc+xxgS
Zq6tCTvCq3R51zUxXc4SFe/nNPH/6ljEF/OKRQeuZE89YarOkhT9c8BDCxnxkoKu
5bMCjGZ55vt85N72Hr2C21qufeKGIP8n3s46hQmLe5KVNmgmC9Zh7HK61e3HTUge
QkP8LphlaIxWqZYxUsy5Eul1++xqD0r3Y1Lti+U3e70x5YG8TlUsNV5X2dzV00xW
nRIlD6gu1d1hPY9IJctseYKqpjVmlP9bhFnuKZsPnsqIFOO1rMO5SELc2PTg7iCH
LWF29Ldin1Jz2pyJSCGRaGqaHeKtym4Sb13L1RhfJ64UStvxAJVY8wmd5/ch73+I
ZMYCzKfNRFQFTwUT4BBqOcD6ugvhqSYD3ymBm+hIXg/xu2KAh+Vc5KkgLUtfFx8e
kf5KKzklVcqDi0bAi19xZ3xzZeghWA9yK3u21yqw1Zg/mWT9P3vYcEC68BtMPipg
hqcNACpkebIuqS9MMyVCgSvP0337PxsBk7dAmZpLM/w8aexeKRPk0achm73qO/gV
zQjHQfZ8jtNsGCTNnwmH
=Dfqh
-----END PGP SIGNATURE-----




More information about the kernel-team mailing list