<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux/drivers/tty/tty_buffer.c, branch v4.1</title>
<subtitle>Mirror of https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/
</subtitle>
<id>https://git.shady.money/linux/atom?h=v4.1</id>
<link rel='self' href='https://git.shady.money/linux/atom?h=v4.1'/>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/'/>
<updated>2015-05-10T17:26:37Z</updated>
<entry>
<title>pty: Fix input race when closing</title>
<updated>2015-05-10T17:26:37Z</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2015-04-13T17:24:34Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=1a48632ffed61352a7810ce089dc5a8bcd505a60'/>
<id>urn:sha1:1a48632ffed61352a7810ce089dc5a8bcd505a60</id>
<content type='text'>
A read() from a pty master may mistakenly indicate EOF (errno == -EIO)
after the pty slave has closed, even though input data remains to be read.
For example,

       pty slave       |        input worker        |    pty master
                       |                            |
                       |                            |   n_tty_read()
pty_write()            |                            |     input avail? no
  add data             |                            |     sleep
  schedule worker  ---&gt;|                            |     .
                       |---&gt; flush_to_ldisc()       |     .
pty_close()            |       fill read buffer     |     .
  wait for worker      |       wakeup reader    ---&gt;|     .
                       |       read buffer full?    |---&gt; input avail ? yes
                       |&lt;---   yes - exit worker    |     copy 4096 bytes to user
  TTY_OTHER_CLOSED &lt;---|                            |&lt;--- kick worker
                       |                            |

		                **** New read() before worker starts ****

                       |                            |   n_tty_read()
                       |                            |     input avail? no
                       |                            |     TTY_OTHER_CLOSED? yes
                       |                            |     return -EIO

Several conditions are required to trigger this race:
1. the ldisc read buffer must become full so the input worker exits
2. the read() count parameter must be &gt;= 4096 so the ldisc read buffer
   is empty
3. the subsequent read() occurs before the kicked worker has processed
   more input

However, the underlying cause of the race is that data is pipelined, while
tty state is not; ie., data already written by the pty slave end is not
yet visible to the pty master end, but state changes by the pty slave end
are visible to the pty master end immediately.

Pipeline the TTY_OTHER_CLOSED state through input worker to the reader.
1. Introduce TTY_OTHER_DONE which is set by the input worker when
   TTY_OTHER_CLOSED is set and either the input buffers are flushed or
   input processing has completed. Readers/polls are woken when
   TTY_OTHER_DONE is set.
2. Reader/poll checks TTY_OTHER_DONE instead of TTY_OTHER_CLOSED.
3. A new input worker is started from pty_close() after setting
   TTY_OTHER_CLOSED, which ensures the TTY_OTHER_DONE state will be
   set if the last input worker is already finished (or just about to
   exit).

Remove tty_flush_to_ldisc(); no in-tree callers.

Fixes: 52bce7f8d4fc ("pty, n_tty: Simplify input processing on final close")
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=96311
BugLink: http://bugs.launchpad.net/bugs/1429756
Cc: &lt;stable@vger.kernel.org&gt; # 3.19+
Reported-by: Andy Whitcroft &lt;apw@canonical.com&gt;
Reported-by: H.J. Lu &lt;hjl.tools@gmail.com&gt;
Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
<entry>
<title>pty: Fix buffer flush deadlock</title>
<updated>2015-02-02T18:11:27Z</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2015-01-17T20:42:05Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=1d1d14da12e79a6c05fbe1a975401f0f56c93316'/>
<id>urn:sha1:1d1d14da12e79a6c05fbe1a975401f0f56c93316</id>
<content type='text'>
The pty driver does not clear its write buffer when commanded.
This is to avoid an apparent deadlock between parallel flushes from
both pty ends; specifically when handling either BRK or INTR input.
However, parallel flushes from this source is not possible since
the pty master can never be set to BRKINT or ISIG. Parallel flushes
from other sources are possible but these do not threaten deadlocks.

Annotate the tty buffer mutex for lockdep to represent the nested
tty_buffer locking which occurs when the pty slave is processing input
(its buffer mutex held) and receives INTR or BRK and acquires the
linked tty buffer mutex via tty_buffer_flush().

Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
<entry>
<title>tty: Flush ldisc buffer atomically with tty flip buffers</title>
<updated>2014-11-06T02:50:43Z</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2014-11-05T17:13:09Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=86c80a8e2ab443e9c4261b3499de4ce808399104'/>
<id>urn:sha1:86c80a8e2ab443e9c4261b3499de4ce808399104</id>
<content type='text'>
tty_ldisc_flush() first clears the line discipline input buffer,
then clears the tty flip buffers. However, this allows for existing
data in the tty flip buffers to be added after the ldisc input
buffer has been cleared, but before the flip buffers have been cleared.

Add an optional ldisc parameter to tty_buffer_flush() to allow
tty_ldisc_flush() to pass the ldisc to clear.

NB: Initially, the plan was to do this automatically in
tty_buffer_flush(). However, an audit of the behavior of existing
line disciplines showed that performing a ldisc buffer flush on
ioctl(TCFLSH) was not always the outcome. For example, some line
disciplines have flush_buffer() methods but not ioctl() methods,
so a -&gt;flush_buffer() command would be unexpected.

Reviewed-by: Alan Cox &lt;alan@linux.intel.com&gt;
Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
<entry>
<title>Staging: speakup: Update __speakup_paste_selection() tty (ab)usage to match vt</title>
<updated>2014-05-23T17:25:11Z</updated>
<author>
<name>Ben Hutchings</name>
<email>ben@decadent.org.uk</email>
</author>
<published>2014-05-19T00:03:06Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=28a821c306889b9f2c3fff49abedc9b2c743eb73'/>
<id>urn:sha1:28a821c306889b9f2c3fff49abedc9b2c743eb73</id>
<content type='text'>
This function is largely a duplicate of paste_selection() in
drivers/tty/vt/selection.c, but with its own selection state.  The
speakup selection mechanism should really be merged with vt.

For now, apply the changes from 'TTY: vt, fix paste_selection ldisc
handling', 'tty: Make ldisc input flow control concurrency-friendly',
and 'tty: Fix unsafe vt paste_selection()'.

References: https://bugs.debian.org/735202
References: https://bugs.debian.org/744015
Reported-by: Paul Gevers &lt;elbrus@debian.org&gt;
Reported-and-tested-by: Jarek Czekalski &lt;jarekczek@poczta.onet.pl&gt;
Signed-off-by: Ben Hutchings &lt;ben@decadent.org.uk&gt;
Cc: &lt;stable@vger.kernel.org&gt; # v3.8 but needs backporting for &lt; 3.12
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
<entry>
<title>tty: Fix lockless tty buffer race</title>
<updated>2014-05-03T22:14:28Z</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2014-05-02T14:56:12Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=62a0d8d7c2b29f92850e4ee3c38e5dfd936e92b2'/>
<id>urn:sha1:62a0d8d7c2b29f92850e4ee3c38e5dfd936e92b2</id>
<content type='text'>
Commit 6a20dbd6caa2358716136144bf524331d70b1e03,
"tty: Fix race condition between __tty_buffer_request_room and flush_to_ldisc"
correctly identifies an unsafe race condition between
__tty_buffer_request_room() and flush_to_ldisc(), where the consumer
flush_to_ldisc() prematurely advances the head before consuming the
last of the data committed. For example:

           CPU 0                     |            CPU 1
__tty_buffer_request_room            | flush_to_ldisc
  ...                                |   ...
                                     |   count = head-&gt;commit - head-&gt;read
  n = tty_buffer_alloc()             |
  b-&gt;commit = b-&gt;used                |
  b-&gt;next = n                        |
                                     |   if (!count)                /* T */
                                     |     if (head-&gt;next == NULL)  /* F */
                                     |     buf-&gt;head = head-&gt;next

In this case, buf-&gt;head has been advanced but head-&gt;commit may have
been updated with a new value.

Instead of reintroducing an unnecessary lock, fix the race locklessly.
Read the commit-next pair in the reverse order of writing, which guarantees
the commit value read is the latest value written if the head is
advancing.

Reported-by: Manfred Schlaegl &lt;manfred.schlaegl@gmx.at&gt;
Cc: &lt;stable@vger.kernel.org&gt; # 3.12.x+
Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
<entry>
<title>Revert "tty: Fix race condition between __tty_buffer_request_room and flush_to_ldisc"</title>
<updated>2014-05-03T22:14:28Z</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2014-05-02T14:56:11Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=5fbf1a65dd53ef313783c34a0e93a6e29def6136'/>
<id>urn:sha1:5fbf1a65dd53ef313783c34a0e93a6e29def6136</id>
<content type='text'>
This reverts commit 6a20dbd6caa2358716136144bf524331d70b1e03.

Although the commit correctly identifies an unsafe race condition
between __tty_buffer_request_room() and flush_to_ldisc(), the commit
fixes the race with an unnecessary spinlock in a lockless algorithm.

The follow-on commit, "tty: Fix lockless tty buffer race" fixes
the race locklessly.

Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
<entry>
<title>tty: Fix race condition between __tty_buffer_request_room and flush_to_ldisc</title>
<updated>2014-04-24T22:18:02Z</updated>
<author>
<name>Manfred Schlaegl</name>
<email>manfred.schlaegl@gmx.at</email>
</author>
<published>2014-04-08T12:42:04Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=6a20dbd6caa2358716136144bf524331d70b1e03'/>
<id>urn:sha1:6a20dbd6caa2358716136144bf524331d70b1e03</id>
<content type='text'>
The race was introduced while development of linux-3.11 by
e8437d7ecbc50198705331449367d401ebb3181f and
e9975fdec0138f1b2a85b9624e41660abd9865d4.
Originally it was found and reproduced on linux-3.12.15 and
linux-3.12.15-rt25, by sending 500 byte blocks with 115kbaud to the
target uart in a loop with 100 milliseconds delay.

In short:
 1. The consumer flush_to_ldisc is on to remove the head tty_buffer.
 2. The producer adds a number of bytes, so that a new tty_buffer must
	be allocated and added by __tty_buffer_request_room.
 3. The consumer removes the head tty_buffer element, without handling
	newly committed data.

Detailed example:
 * Initial buffer:
   * Head, Tail -&gt; 0: used=250; commit=250; read=240; next=NULL
 * Consumer: ''flush_to_ldisc''
   * consumed 10 Byte
   * buffer:
     * Head, Tail -&gt; 0: used=250; commit=250; read=250; next=NULL
{{{
		count = head-&gt;commit - head-&gt;read;	// count = 0
		if (!count) {				// enter
			// INTERRUPTED BY PRODUCER -&gt;
			if (head-&gt;next == NULL)
				break;
			buf-&gt;head = head-&gt;next;
			tty_buffer_free(port, head);
			continue;
		}
}}}
 * Producer: tty_insert_flip_... 10 bytes + tty_flip_buffer_push
   * buffer:
     * Head, Tail -&gt; 0: used=250; commit=250; read=250; next=NULL
   * added 6 bytes: head-element filled to maximum.
     * buffer:
       * Head, Tail -&gt; 0: used=256; commit=250; read=250; next=NULL
   * added 4 bytes: __tty_buffer_request_room is called
     * buffer:
       * Head -&gt; 0: used=256; commit=256; read=250; next=1
       * Tail -&gt; 1: used=4; commit=0; read=250 next=NULL
   * push (tty_flip_buffer_push)
     * buffer:
       * Head -&gt; 0: used=256; commit=256; read=250; next=1
       * Tail -&gt; 1: used=4; commit=4; read=250 next=NULL
 * Consumer
{{{
		count = head-&gt;commit - head-&gt;read;
		if (!count) {
			// INTERRUPTED BY PRODUCER &lt;-
			if (head-&gt;next == NULL)		// -&gt; no break
				break;
			buf-&gt;head = head-&gt;next;
			tty_buffer_free(port, head);
			// ERROR: tty_buffer head freed -&gt; 6 bytes lost
			continue;
		}
}}}

This patch reintroduces a spin_lock to protect this case. Perhaps later
a lock-less solution could be found.

Signed-off-by: Manfred Schlaegl &lt;manfred.schlaegl@gmx.at&gt;
Cc: stable &lt;stable@vger.kernel.org&gt; # 3.11
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
<entry>
<title>tty: Fix low_latency BUG</title>
<updated>2014-03-01T00:31:00Z</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2014-02-22T12:31:21Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=a9c3f68f3cd8d55f809fbdb0c138ed061ea1bd25'/>
<id>urn:sha1:a9c3f68f3cd8d55f809fbdb0c138ed061ea1bd25</id>
<content type='text'>
The user-settable knob, low_latency, has been the source of
several BUG reports which stem from flush_to_ldisc() running
in interrupt context. Since 3.12, which added several sleeping
locks (termios_rwsem and buf-&gt;lock) to the input processing path,
the frequency of these BUG reports has increased.

Note that changes in 3.12 did not introduce this regression;
sleeping locks were first added to the input processing path
with the removal of the BKL from N_TTY in commit
a88a69c91256418c5907c2f1f8a0ec0a36f9e6cc,
'n_tty: Fix loss of echoed characters and remove bkl from n_tty'
and later in commit 38db89799bdf11625a831c5af33938dcb11908b6,
'tty: throttling race fix'. Since those changes, executing
flush_to_ldisc() in interrupt_context (ie, low_latency set), is unsafe.

However, since most devices do not validate if the low_latency
setting is appropriate for the context (process or interrupt) in
which they receive data, some reports are due to misconfiguration.
Further, serial dma devices for which dma fails, resort to
interrupt receiving as a backup without resetting low_latency.

Historically, low_latency was used to force wake-up the reading
process rather than wait for the next scheduler tick. The
effect was to trim multiple milliseconds of latency from
when the process would receive new data.

Recent tests [1] have shown that the reading process now receives
data with only 10's of microseconds latency without low_latency set.

Remove the low_latency rx steering from tty_flip_buffer_push();
however, leave the knob as an optional hint to drivers that can
tune their rx fifos and such like. Cleanup stale code comments
regarding low_latency.

[1] https://lkml.org/lkml/2014/2/20/434

"Yay.. thats an annoying historical pain in the butt gone."
	-- Alan Cox

Reported-by: Beat Bolli &lt;bbolli@ewanet.ch&gt;
Reported-by: Pavel Roskin &lt;proski@gnu.org&gt;
Acked-by: David Sterba &lt;dsterba@suse.cz&gt;
Cc: Grant Edwards &lt;grant.b.edwards@gmail.com&gt;
Cc: Stanislaw Gruszka &lt;sgruszka@redhat.com&gt;
Cc: Hal Murray &lt;murray+fedora@ip-64-139-1-69.sjc.megapath.net&gt;
Cc: &lt;stable@vger.kernel.org&gt; # 3.12.x+
Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Alan Cox &lt;alan@linux.intel.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
<entry>
<title>tty: delete non-required instances of include &lt;linux/init.h&gt;</title>
<updated>2014-01-08T01:05:21Z</updated>
<author>
<name>Paul Gortmaker</name>
<email>paul.gortmaker@windriver.com</email>
</author>
<published>2014-01-03T00:23:47Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=f8e87cb4a19aa5f5a1ce22e130da0f4a7fa2d5f3'/>
<id>urn:sha1:f8e87cb4a19aa5f5a1ce22e130da0f4a7fa2d5f3</id>
<content type='text'>
None of these files are actually using any __init type directives
and hence don't need to include &lt;linux/init.h&gt;.  Most are just a
left over from __devinit and __cpuinit removal, or simply due to
code getting copied from one driver to the next.

Signed-off-by: Paul Gortmaker &lt;paul.gortmaker@windriver.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
<entry>
<title>tty: Halve flip buffer GFP_ATOMIC memory consumption</title>
<updated>2013-12-09T19:09:24Z</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2013-12-09T14:23:52Z</published>
<link rel='alternate' type='text/html' href='https://git.shady.money/linux/commit/?id=acc0f67f307f52f7aec1cffdc40a786c15dd21d9'/>
<id>urn:sha1:acc0f67f307f52f7aec1cffdc40a786c15dd21d9</id>
<content type='text'>
tty flip buffers use GFP_ATOMIC allocations for received data
which is to be processed by the line discipline. For each byte
received, an extra byte is used to indicate the error status of
that byte.

Instead, if the received data is error-free, encode the entire
buffer without status bytes.

Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
</entry>
</feed>
