diff options
author | Stanislav Kozina <skozina@redhat.com> | 2012-08-09 14:48:58 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-08-10 13:13:11 -0700 |
commit | 00aaae033e323af33740e7012a8ba4b0fa6dce20 (patch) | |
tree | 152d5cfb0186d2c4c5fadae2e79cf49d154be911 /drivers/tty | |
parent | 857196e2758f01ec40f93429013963ca5f22cbae (diff) | |
download | op-kernel-dev-00aaae033e323af33740e7012a8ba4b0fa6dce20.zip op-kernel-dev-00aaae033e323af33740e7012a8ba4b0fa6dce20.tar.gz |
tty: Fix possible race in n_tty_read()
Fix possible panic caused by unlocked access to tty->read_cnt in
while-loop condition in n_tty_read().
Signed-off-by: Stanislav Kozina <skozina@redhat.com>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r-- | drivers/tty/n_tty.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 101790c..20de673 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -1838,13 +1838,13 @@ do_it_again: if (tty->icanon && !L_EXTPROC(tty)) { /* N.B. avoid overrun if nr == 0 */ + spin_lock_irqsave(&tty->read_lock, flags); while (nr && tty->read_cnt) { int eol; eol = test_and_clear_bit(tty->read_tail, tty->read_flags); c = tty->read_buf[tty->read_tail]; - spin_lock_irqsave(&tty->read_lock, flags); tty->read_tail = ((tty->read_tail+1) & (N_TTY_BUF_SIZE-1)); tty->read_cnt--; @@ -1862,15 +1862,19 @@ do_it_again: if (tty_put_user(tty, c, b++)) { retval = -EFAULT; b--; + spin_lock_irqsave(&tty->read_lock, flags); break; } nr--; } if (eol) { tty_audit_push(tty); + spin_lock_irqsave(&tty->read_lock, flags); break; } + spin_lock_irqsave(&tty->read_lock, flags); } + spin_unlock_irqrestore(&tty->read_lock, flags); if (retval) break; } else { |