aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/tty
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2015-01-16 15:05:39 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-02-02 13:11:26 -0500
commitfb5ef9e7da39968fec6d6f37f20a23d23740c75e (patch)
treed28c70a23bf768777088a72b7a3d499477e2d9dd /drivers/tty
parent06c49f9fa31f026e00a15cc6487b4d8d99b0e333 (diff)
n_tty: Fix read buffer overwrite when no newline
In canon mode, the read buffer head will advance over the buffer tail if the input > 4095 bytes without receiving a line termination char. Discard additional input until a line termination is received. Before evaluating for overflow, the 'room' value is normalized for I_PARMRK and 1 byte is reserved for line termination (even in !icanon mode, in case the mode is switched). The following table shows the transform: actual buffer | 'room' value before overflow calc space avail | !I_PARMRK | I_PARMRK -------------------------------------------------- 0 | -1 | -1 1 | 0 | 0 2 | 1 | 0 3 | 2 | 0 4+ | 3 | 1 When !icanon or when icanon and the read buffer contains newlines, normalized 'room' values of -1 and 0 are clamped to 0, and 'overflow' is 0, so read_head is not adjusted and the input i/o loop exits (setting no_room if called from flush_to_ldisc()). No input is discarded since the reader does have input available to read which ensures forward progress. When icanon and the read buffer does not contain newlines and the normalized 'room' value is 0, then overflow and room are reset to 1, so that the i/o loop will process the next input char normally (except for parity errors which are ignored). Thus, erasures, signalling chars, 7-bit mode, etc. will continue to be handled properly. If the input char processed was not a line termination char, then the canon_head index will not have advanced, so the normalized 'room' value will now be -1 and 'overflow' will be set, which indicates the read_head can safely be reset, effectively erasing the last char processed. If the input char processed was a line termination, then the canon_head index will have advanced, so 'overflow' is cleared to 0, the read_head is not reset, and 'room' is cleared to 0, which exits the i/o loop (because the reader now have input available to read which ensures forward progress). Note that it is possible for a line termination to be received, and for the reader to copy the line to the user buffer before the input i/o loop is ready to process the next input char. This is why the i/o loop recomputes the room/overflow state with every input char while handling overflow. Finally, if the input data was processed without receiving a line termination (so that overflow is still set), the pty driver must receive a write wakeup. A pty writer may be waiting to write more data in n_tty_write() but without unthrottling here that wakeup will not arrive, and forward progress will halt. (Normally, the pty writer is woken when the reader reads data out of the buffer and more space become available). Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty')
-rw-r--r--drivers/tty/n_tty.c92
1 files changed, 62 insertions, 30 deletions
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index 7aeabb719526..5793aa0d3bfb 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -225,8 +225,6 @@ static void n_tty_check_throttle(struct tty_struct *tty)
225{ 225{
226 struct n_tty_data *ldata = tty->disc_data; 226 struct n_tty_data *ldata = tty->disc_data;
227 227
228 if (tty->driver->type == TTY_DRIVER_TYPE_PTY)
229 return;
230 /* 228 /*
231 * Check the remaining room for the input canonicalization 229 * Check the remaining room for the input canonicalization
232 * mode. We don't want to throttle the driver if we're in 230 * mode. We don't want to throttle the driver if we're in
@@ -1483,23 +1481,6 @@ n_tty_receive_char_lnext(struct tty_struct *tty, unsigned char c, char flag)
1483 n_tty_receive_char_flagged(tty, c, flag); 1481 n_tty_receive_char_flagged(tty, c, flag);
1484} 1482}
1485 1483
1486/**
1487 * n_tty_receive_buf - data receive
1488 * @tty: terminal device
1489 * @cp: buffer
1490 * @fp: flag buffer
1491 * @count: characters
1492 *
1493 * Called by the terminal driver when a block of characters has
1494 * been received. This function must be called from soft contexts
1495 * not from interrupt context. The driver is responsible for making
1496 * calls one at a time and in order (or using flush_to_ldisc)
1497 *
1498 * n_tty_receive_buf()/producer path:
1499 * claims non-exclusive termios_rwsem
1500 * publishes commit_head or canon_head
1501 */
1502
1503static void 1484static void
1504n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp, 1485n_tty_receive_buf_real_raw(struct tty_struct *tty, const unsigned char *cp,
1505 char *fp, int count) 1486 char *fp, int count)
@@ -1658,12 +1639,45 @@ static void __receive_buf(struct tty_struct *tty, const unsigned char *cp,
1658 } 1639 }
1659} 1640}
1660 1641
1642/**
1643 * n_tty_receive_buf_common - process input
1644 * @tty: device to receive input
1645 * @cp: input chars
1646 * @fp: flags for each char (if NULL, all chars are TTY_NORMAL)
1647 * @count: number of input chars in @cp
1648 *
1649 * Called by the terminal driver when a block of characters has
1650 * been received. This function must be called from soft contexts
1651 * not from interrupt context. The driver is responsible for making
1652 * calls one at a time and in order (or using flush_to_ldisc)
1653 *
1654 * Returns the # of input chars from @cp which were processed.
1655 *
1656 * In canonical mode, the maximum line length is 4096 chars (including
1657 * the line termination char); lines longer than 4096 chars are
1658 * truncated. After 4095 chars, input data is still processed but
1659 * not stored. Overflow processing ensures the tty can always
1660 * receive more input until at least one line can be read.
1661 *
1662 * In non-canonical mode, the read buffer will only accept 4095 chars;
1663 * this provides the necessary space for a newline char if the input
1664 * mode is switched to canonical.
1665 *
1666 * Note it is possible for the read buffer to _contain_ 4096 chars
1667 * in non-canonical mode: the read buffer could already contain the
1668 * maximum canon line of 4096 chars when the mode is switched to
1669 * non-canonical.
1670 *
1671 * n_tty_receive_buf()/producer path:
1672 * claims non-exclusive termios_rwsem
1673 * publishes commit_head or canon_head
1674 */
1661static int 1675static int
1662n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp, 1676n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
1663 char *fp, int count, int flow) 1677 char *fp, int count, int flow)
1664{ 1678{
1665 struct n_tty_data *ldata = tty->disc_data; 1679 struct n_tty_data *ldata = tty->disc_data;
1666 int room, n, rcvd = 0; 1680 int room, n, rcvd = 0, overflow;
1667 1681
1668 down_read(&tty->termios_rwsem); 1682 down_read(&tty->termios_rwsem);
1669 1683
@@ -1683,19 +1697,27 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
1683 */ 1697 */
1684 size_t tail = smp_load_acquire(&ldata->read_tail); 1698 size_t tail = smp_load_acquire(&ldata->read_tail);
1685 1699
1686 room = N_TTY_BUF_SIZE - (ldata->read_head - tail) - 1; 1700 room = N_TTY_BUF_SIZE - (ldata->read_head - tail);
1687 if (I_PARMRK(tty)) 1701 if (I_PARMRK(tty))
1688 room /= 3; 1702 room = (room + 2) / 3;
1689 if (room <= 0) 1703 room--;
1690 room = ldata->icanon && ldata->canon_head == tail; 1704 if (room <= 0) {
1705 overflow = ldata->icanon && ldata->canon_head == tail;
1706 if (overflow && room < 0)
1707 ldata->read_head--;
1708 room = overflow;
1709 ldata->no_room = flow && !room;
1710 } else
1711 overflow = 0;
1691 1712
1692 n = min(count, room); 1713 n = min(count, room);
1693 if (!n) { 1714 if (!n)
1694 if (flow && !room)
1695 ldata->no_room = 1;
1696 break; 1715 break;
1697 } 1716
1698 __receive_buf(tty, cp, fp, n); 1717 /* ignore parity errors if handling overflow */
1718 if (!overflow || !fp || *fp != TTY_PARITY)
1719 __receive_buf(tty, cp, fp, n);
1720
1699 cp += n; 1721 cp += n;
1700 if (fp) 1722 if (fp)
1701 fp += n; 1723 fp += n;
@@ -1704,7 +1726,17 @@ n_tty_receive_buf_common(struct tty_struct *tty, const unsigned char *cp,
1704 } 1726 }
1705 1727
1706 tty->receive_room = room; 1728 tty->receive_room = room;
1707 n_tty_check_throttle(tty); 1729
1730 /* Unthrottle if handling overflow on pty */
1731 if (tty->driver->type == TTY_DRIVER_TYPE_PTY) {
1732 if (overflow) {
1733 tty_set_flow_change(tty, TTY_UNTHROTTLE_SAFE);
1734 tty_unthrottle_safe(tty);
1735 __tty_set_flow_change(tty, 0);
1736 }
1737 } else
1738 n_tty_check_throttle(tty);
1739
1708 up_read(&tty->termios_rwsem); 1740 up_read(&tty->termios_rwsem);
1709 1741
1710 return rcvd; 1742 return rcvd;