summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJaeden Amero <jaeden.amero@ni.com>2012-07-27 15:43:11 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-08-10 22:14:54 +0200
commit090abf7b91645c1936ba959b1e1cd6d09110779c (patch)
tree49045c02ba80b131e604a3e13ec4081c9cd62832
parenttty: Fix possible race in n_tty_read() (diff)
downloadlinux-090abf7b91645c1936ba959b1e1cd6d09110779c.tar.xz
linux-090abf7b91645c1936ba959b1e1cd6d09110779c.zip
n_tty: Don't lose characters when PARMRK is enabled
When PARMRK is set and large transfers of characters that will get marked are being received, n_tty could drop data silently (i.e. without reporting any error to the client). This is because characters have the potential to take up to three bytes in the line discipline (when they get marked with parity or framing errors), but the amount of free space reported to tty_buffer flush_to_ldisc (via tty->receive_room) is based on the pre-marked data size. With this patch, the n_tty layer will no longer assume that each byte will only take up one byte in the line discipline. Instead, it will make an overly conservative estimate that each byte will take up three bytes in the line discipline when PARMRK is set. Signed-off-by: Jaeden Amero <jaeden.amero@ni.com> Acked-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/tty/n_tty.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 20de673a7730..6259242b7858 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -92,10 +92,18 @@ static inline int tty_put_user(struct tty_struct *tty, unsigned char x,
static void n_tty_set_room(struct tty_struct *tty)
{
- /* tty->read_cnt is not read locked ? */
- int left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+ int left;
int old_left;
+ /* tty->read_cnt is not read locked ? */
+ if (I_PARMRK(tty)) {
+ /* Multiply read_cnt by 3, since each byte might take up to
+ * three times as many spaces when PARMRK is set (depending on
+ * its flags, e.g. parity error). */
+ left = N_TTY_BUF_SIZE - tty->read_cnt * 3 - 1;
+ } else
+ left = N_TTY_BUF_SIZE - tty->read_cnt - 1;
+
/*
* If we are doing input canonicalization, and there are no
* pending newlines, let characters through without limit, so