diff options
author | Stanislav Kozina <skozina@redhat.com> | 2012-08-09 09:48:58 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-08-10 16:13:11 -0400 |
commit | 00aaae033e323af33740e7012a8ba4b0fa6dce20 (patch) | |
tree | 152d5cfb0186d2c4c5fadae2e79cf49d154be911 /drivers/tty/n_tty.c | |
parent | 857196e2758f01ec40f93429013963ca5f22cbae (diff) |
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/n_tty.c')
-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 101790cea4ae..20de673a7730 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c | |||
@@ -1838,13 +1838,13 @@ do_it_again: | |||
1838 | 1838 | ||
1839 | if (tty->icanon && !L_EXTPROC(tty)) { | 1839 | if (tty->icanon && !L_EXTPROC(tty)) { |
1840 | /* N.B. avoid overrun if nr == 0 */ | 1840 | /* N.B. avoid overrun if nr == 0 */ |
1841 | spin_lock_irqsave(&tty->read_lock, flags); | ||
1841 | while (nr && tty->read_cnt) { | 1842 | while (nr && tty->read_cnt) { |
1842 | int eol; | 1843 | int eol; |
1843 | 1844 | ||
1844 | eol = test_and_clear_bit(tty->read_tail, | 1845 | eol = test_and_clear_bit(tty->read_tail, |
1845 | tty->read_flags); | 1846 | tty->read_flags); |
1846 | c = tty->read_buf[tty->read_tail]; | 1847 | c = tty->read_buf[tty->read_tail]; |
1847 | spin_lock_irqsave(&tty->read_lock, flags); | ||
1848 | tty->read_tail = ((tty->read_tail+1) & | 1848 | tty->read_tail = ((tty->read_tail+1) & |
1849 | (N_TTY_BUF_SIZE-1)); | 1849 | (N_TTY_BUF_SIZE-1)); |
1850 | tty->read_cnt--; | 1850 | tty->read_cnt--; |
@@ -1862,15 +1862,19 @@ do_it_again: | |||
1862 | if (tty_put_user(tty, c, b++)) { | 1862 | if (tty_put_user(tty, c, b++)) { |
1863 | retval = -EFAULT; | 1863 | retval = -EFAULT; |
1864 | b--; | 1864 | b--; |
1865 | spin_lock_irqsave(&tty->read_lock, flags); | ||
1865 | break; | 1866 | break; |
1866 | } | 1867 | } |
1867 | nr--; | 1868 | nr--; |
1868 | } | 1869 | } |
1869 | if (eol) { | 1870 | if (eol) { |
1870 | tty_audit_push(tty); | 1871 | tty_audit_push(tty); |
1872 | spin_lock_irqsave(&tty->read_lock, flags); | ||
1871 | break; | 1873 | break; |
1872 | } | 1874 | } |
1875 | spin_lock_irqsave(&tty->read_lock, flags); | ||
1873 | } | 1876 | } |
1877 | spin_unlock_irqrestore(&tty->read_lock, flags); | ||
1874 | if (retval) | 1878 | if (retval) |
1875 | break; | 1879 | break; |
1876 | } else { | 1880 | } else { |