<feed xmlns='http://www.w3.org/2005/Atom'>
<title>linux-toradex.git/drivers/tty/n_tty.c, branch v3.10.78</title>
<subtitle>Linux kernel for Apalis and Colibri modules</subtitle>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/'/>
<entry>
<title>n_tty: Fix n_tty_write crash when echoing in raw mode</title>
<updated>2014-05-13T11:59:40+00:00</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2014-05-03T12:04:59+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=abb5100737bba3f82b5514350fea89ca361ac66c'/>
<id>abb5100737bba3f82b5514350fea89ca361ac66c</id>
<content type='text'>
commit 4291086b1f081b869c6d79e5b7441633dc3ace00 upstream.

The tty atomic_write_lock does not provide an exclusion guarantee for
the tty driver if the termios settings are LECHO &amp; !OPOST.  And since
it is unexpected and not allowed to call TTY buffer helpers like
tty_insert_flip_string concurrently, this may lead to crashes when
concurrect writers call pty_write. In that case the following two
writers:
* the ECHOing from a workqueue and
* pty_write from the process
race and can overflow the corresponding TTY buffer like follows.

If we look into tty_insert_flip_string_fixed_flag, there is:
  int space = __tty_buffer_request_room(port, goal, flags);
  struct tty_buffer *tb = port-&gt;buf.tail;
  ...
  memcpy(char_buf_ptr(tb, tb-&gt;used), chars, space);
  ...
  tb-&gt;used += space;

so the race of the two can result in something like this:
              A                                B
__tty_buffer_request_room
                                  __tty_buffer_request_room
memcpy(buf(tb-&gt;used), ...)
tb-&gt;used += space;
                                  memcpy(buf(tb-&gt;used), ...) -&gt;BOOM

B's memcpy is past the tty_buffer due to the previous A's tb-&gt;used
increment.

Since the N_TTY line discipline input processing can output
concurrently with a tty write, obtain the N_TTY ldisc output_lock to
serialize echo output with normal tty writes.  This ensures the tty
buffer helper tty_insert_flip_string is not called concurrently and
everything is fine.

Note that this is nicely reproducible by an ordinary user using
forkpty and some setup around that (raw termios + ECHO). And it is
present in kernels at least after commit
d945cb9cce20ac7143c2de8d88b187f62db99bdc (pty: Rework the pty layer to
use the normal buffering logic) in 2.6.31-rc3.

js: add more info to the commit log
js: switch to bool
js: lock unconditionally
js: lock only the tty-&gt;ops-&gt;write call

References: CVE-2014-0196
Reported-and-tested-by: Jiri Slaby &lt;jslaby@suse.cz&gt;
Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Jiri Slaby &lt;jslaby@suse.cz&gt;
Cc: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Cc: Alan Cox &lt;alan@lxorguk.ukuu.org.uk&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
commit 4291086b1f081b869c6d79e5b7441633dc3ace00 upstream.

The tty atomic_write_lock does not provide an exclusion guarantee for
the tty driver if the termios settings are LECHO &amp; !OPOST.  And since
it is unexpected and not allowed to call TTY buffer helpers like
tty_insert_flip_string concurrently, this may lead to crashes when
concurrect writers call pty_write. In that case the following two
writers:
* the ECHOing from a workqueue and
* pty_write from the process
race and can overflow the corresponding TTY buffer like follows.

If we look into tty_insert_flip_string_fixed_flag, there is:
  int space = __tty_buffer_request_room(port, goal, flags);
  struct tty_buffer *tb = port-&gt;buf.tail;
  ...
  memcpy(char_buf_ptr(tb, tb-&gt;used), chars, space);
  ...
  tb-&gt;used += space;

so the race of the two can result in something like this:
              A                                B
__tty_buffer_request_room
                                  __tty_buffer_request_room
memcpy(buf(tb-&gt;used), ...)
tb-&gt;used += space;
                                  memcpy(buf(tb-&gt;used), ...) -&gt;BOOM

B's memcpy is past the tty_buffer due to the previous A's tb-&gt;used
increment.

Since the N_TTY line discipline input processing can output
concurrently with a tty write, obtain the N_TTY ldisc output_lock to
serialize echo output with normal tty writes.  This ensures the tty
buffer helper tty_insert_flip_string is not called concurrently and
everything is fine.

Note that this is nicely reproducible by an ordinary user using
forkpty and some setup around that (raw termios + ECHO). And it is
present in kernels at least after commit
d945cb9cce20ac7143c2de8d88b187f62db99bdc (pty: Rework the pty layer to
use the normal buffering logic) in 2.6.31-rc3.

js: add more info to the commit log
js: switch to bool
js: lock unconditionally
js: lock only the tty-&gt;ops-&gt;write call

References: CVE-2014-0196
Reported-and-tested-by: Jiri Slaby &lt;jslaby@suse.cz&gt;
Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Jiri Slaby &lt;jslaby@suse.cz&gt;
Cc: Linus Torvalds &lt;torvalds@linux-foundation.org&gt;
Cc: Alan Cox &lt;alan@lxorguk.ukuu.org.uk&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;

</pre>
</div>
</content>
</entry>
<entry>
<title>TTY: Fix tty miss restart after we turn off flow-control</title>
<updated>2013-05-20T19:15:59+00:00</updated>
<author>
<name>Wang YanQing</name>
<email>udknight@gmail.com</email>
</author>
<published>2013-05-09T06:16:47+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=dab73b4eb9ef924a2b90dab84e539076d82b256f'/>
<id>dab73b4eb9ef924a2b90dab84e539076d82b256f</id>
<content type='text'>
I meet emacs hang in start if I do the operation below:
  1: echo 3 &gt; /proc/sys/vm/drop_caches
  2: emacs BigFile
  3: Press CTRL-S follow 2 immediately

Then emacs hang on, CTRL-Q can't resume, the terminal
hang on, you can do nothing with this terminal except
close it.

The reason is before emacs takeover control the tty,
we use CTRL-S to XOFF it. Then when emacs takeover the
control, it may don't use the flow-control, so emacs hang.
This patch fix it.

This patch will fix a kind of strange tty relation hang problem,
I believe I meet it with vim in ssh, and also see below bug report:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=465823

Signed-off-by: Wang YanQing &lt;udknight@gmail.com&gt;
Cc: stable &lt;stable@vger.kernel.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
I meet emacs hang in start if I do the operation below:
  1: echo 3 &gt; /proc/sys/vm/drop_caches
  2: emacs BigFile
  3: Press CTRL-S follow 2 immediately

Then emacs hang on, CTRL-Q can't resume, the terminal
hang on, you can do nothing with this terminal except
close it.

The reason is before emacs takeover control the tty,
we use CTRL-S to XOFF it. Then when emacs takeover the
control, it may don't use the flow-control, so emacs hang.
This patch fix it.

This patch will fix a kind of strange tty relation hang problem,
I believe I meet it with vim in ssh, and also see below bug report:
http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=465823

Signed-off-by: Wang YanQing &lt;udknight@gmail.com&gt;
Cc: stable &lt;stable@vger.kernel.org&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>n_tty: Fully initialize ldisc before restarting buffer work</title>
<updated>2013-03-18T23:44:01+00:00</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2013-03-11T20:44:32+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=b66f4fa509153ca9d313075806d5c6425dfa43c5'/>
<id>b66f4fa509153ca9d313075806d5c6425dfa43c5</id>
<content type='text'>
Buffer work may already be pending when the n_tty ldisc is re-opened,
eg., when setting the ldisc (via TIOCSETD ioctl) and when hanging up
the tty. Since n_tty_set_room() may restart buffer work, first ensure
the ldisc is completely initialized.

Factor n_tty_set_room() out of reset_buffer_flags() (only 2 callers)
and reorganize n_tty_open() to set termios last; buffer work will
be restarted there if necessary, after the char_map is properly
initialized.

Fixes this WARNING:

[  549.561769] ------------[ cut here ]------------
[  549.598755] WARNING: at drivers/tty/n_tty.c:160 n_tty_set_room+0xff/0x130()
[  549.604058] scheduling buffer work for halted ldisc
[  549.607741] Pid: 9417, comm: trinity-child28 Tainted: G      D W 3.7.0-next-20121217-sasha-00023-g8689ef9 #219
[  549.652580] Call Trace:
[  549.662754]  [&lt;ffffffff81c432cf&gt;] ? n_tty_set_room+0xff/0x130
[  549.665458]  [&lt;ffffffff8110cae7&gt;] warn_slowpath_common+0x87/0xb0
[  549.668257]  [&lt;ffffffff8110cb71&gt;] warn_slowpath_fmt+0x41/0x50
[  549.671007]  [&lt;ffffffff81c432cf&gt;] n_tty_set_room+0xff/0x130
[  549.673268]  [&lt;ffffffff81c44597&gt;] reset_buffer_flags+0x137/0x150
[  549.675607]  [&lt;ffffffff81c45b71&gt;] n_tty_open+0x131/0x1c0
[  549.677699]  [&lt;ffffffff81c47824&gt;] tty_ldisc_open.isra.5+0x54/0x70
[  549.680147]  [&lt;ffffffff81c482bf&gt;] tty_ldisc_hangup+0x11f/0x1e0
[  549.682409]  [&lt;ffffffff81c3fa17&gt;] __tty_hangup+0x137/0x440
[  549.684634]  [&lt;ffffffff81c3fd49&gt;] tty_vhangup+0x9/0x10
[  549.686443]  [&lt;ffffffff81c4a42c&gt;] pty_close+0x14c/0x160
[  549.688446]  [&lt;ffffffff81c41225&gt;] tty_release+0xd5/0x490
[  549.690460]  [&lt;ffffffff8127d8a2&gt;] __fput+0x122/0x250
[  549.692577]  [&lt;ffffffff8127d9d9&gt;] ____fput+0x9/0x10
[  549.694534]  [&lt;ffffffff811348c2&gt;] task_work_run+0xb2/0xf0
[  549.696349]  [&lt;ffffffff81113c6d&gt;] do_exit+0x36d/0x580
[  549.698286]  [&lt;ffffffff8107d964&gt;] ? syscall_trace_enter+0x24/0x2e0
[  549.702729]  [&lt;ffffffff81113f4a&gt;] do_group_exit+0x8a/0xc0
[  549.706775]  [&lt;ffffffff81113f92&gt;] sys_exit_group+0x12/0x20
[  549.711088]  [&lt;ffffffff83cfab18&gt;] tracesys+0xe1/0xe6
[  549.728001] ---[ end trace 73eb41728f11f87e ]---

Reported-by: Sasha Levin &lt;levinsasha928@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>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Buffer work may already be pending when the n_tty ldisc is re-opened,
eg., when setting the ldisc (via TIOCSETD ioctl) and when hanging up
the tty. Since n_tty_set_room() may restart buffer work, first ensure
the ldisc is completely initialized.

Factor n_tty_set_room() out of reset_buffer_flags() (only 2 callers)
and reorganize n_tty_open() to set termios last; buffer work will
be restarted there if necessary, after the char_map is properly
initialized.

Fixes this WARNING:

[  549.561769] ------------[ cut here ]------------
[  549.598755] WARNING: at drivers/tty/n_tty.c:160 n_tty_set_room+0xff/0x130()
[  549.604058] scheduling buffer work for halted ldisc
[  549.607741] Pid: 9417, comm: trinity-child28 Tainted: G      D W 3.7.0-next-20121217-sasha-00023-g8689ef9 #219
[  549.652580] Call Trace:
[  549.662754]  [&lt;ffffffff81c432cf&gt;] ? n_tty_set_room+0xff/0x130
[  549.665458]  [&lt;ffffffff8110cae7&gt;] warn_slowpath_common+0x87/0xb0
[  549.668257]  [&lt;ffffffff8110cb71&gt;] warn_slowpath_fmt+0x41/0x50
[  549.671007]  [&lt;ffffffff81c432cf&gt;] n_tty_set_room+0xff/0x130
[  549.673268]  [&lt;ffffffff81c44597&gt;] reset_buffer_flags+0x137/0x150
[  549.675607]  [&lt;ffffffff81c45b71&gt;] n_tty_open+0x131/0x1c0
[  549.677699]  [&lt;ffffffff81c47824&gt;] tty_ldisc_open.isra.5+0x54/0x70
[  549.680147]  [&lt;ffffffff81c482bf&gt;] tty_ldisc_hangup+0x11f/0x1e0
[  549.682409]  [&lt;ffffffff81c3fa17&gt;] __tty_hangup+0x137/0x440
[  549.684634]  [&lt;ffffffff81c3fd49&gt;] tty_vhangup+0x9/0x10
[  549.686443]  [&lt;ffffffff81c4a42c&gt;] pty_close+0x14c/0x160
[  549.688446]  [&lt;ffffffff81c41225&gt;] tty_release+0xd5/0x490
[  549.690460]  [&lt;ffffffff8127d8a2&gt;] __fput+0x122/0x250
[  549.692577]  [&lt;ffffffff8127d9d9&gt;] ____fput+0x9/0x10
[  549.694534]  [&lt;ffffffff811348c2&gt;] task_work_run+0xb2/0xf0
[  549.696349]  [&lt;ffffffff81113c6d&gt;] do_exit+0x36d/0x580
[  549.698286]  [&lt;ffffffff8107d964&gt;] ? syscall_trace_enter+0x24/0x2e0
[  549.702729]  [&lt;ffffffff81113f4a&gt;] do_group_exit+0x8a/0xc0
[  549.706775]  [&lt;ffffffff81113f92&gt;] sys_exit_group+0x12/0x20
[  549.711088]  [&lt;ffffffff83cfab18&gt;] tracesys+0xe1/0xe6
[  549.728001] ---[ end trace 73eb41728f11f87e ]---

Reported-by: Sasha Levin &lt;levinsasha928@gmail.com&gt;
Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>n_tty: Correct unthrottle-with-buffer-flush comments</title>
<updated>2013-03-18T23:38:58+00:00</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2013-03-11T20:44:31+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=25518c68b334aa977d857dd71dd53f694ffb11e8'/>
<id>25518c68b334aa977d857dd71dd53f694ffb11e8</id>
<content type='text'>
The driver is no longer unthrottled on buffer reset, so remove
comments that claim it is.

Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
The driver is no longer unthrottled on buffer reset, so remove
comments that claim it is.

Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>n_tty: Don't flush buffer when closing ldisc</title>
<updated>2013-03-18T23:32:46+00:00</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2013-03-11T20:44:23+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=79901317ce80c43a0249ccc6e3fea9d0968e159e'/>
<id>79901317ce80c43a0249ccc6e3fea9d0968e159e</id>
<content type='text'>
A buffer flush is both undesirable and unnecessary when the ldisc
is closing. A buffer flush performs the following:
 1. resets ldisc data fields to their initial state
 2. resets tty-&gt;receive_room to indicate more data can be sent
 3. schedules buffer work to receive more data
 4. signals a buffer flush has happened to linked pty in packet mode

Since the ldisc has been halted and the tty may soon be destructed,
buffer work must not be scheduled as that work might access
an invalid tty and ldisc state. Also, the ldisc read buffer is about
to be freed, so that's pointless.

Resetting the ldisc data fields is pointless as well since that
structure is about to be freed.

Resetting tty-&gt;receive_room is unnecessary, as it will be properly
reset if a new ldisc is reopened. Besides, resetting the original
receive_room value would be wrong since the read buffer will be
gone.

Since the packet mode flush is observable from userspace, this
behavior has been preserved.

The test jig originally authored by Ilya Zykov &lt;ilya@ilyx.ru&gt; and
signed off by him is included below. The test jig prompts the
following warnings which this patch fixes.

[   38.051111] ------------[ cut here ]------------
[   38.052113] WARNING: at drivers/tty/n_tty.c:160 n_tty_set_room.part.6+0x8b/0xa0()
[   38.053916] Hardware name: Bochs
[   38.054819] Modules linked in: netconsole configfs bnep rfcomm bluetooth parport_pc ppdev snd_hda_intel snd_hda_codec
snd_hwdep snd_pcm snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq psmouse snd_timer serio_raw mac_hid snd_seq_device
snd microcode lp parport virtio_balloon soundcore i2c_piix4 snd_page_alloc floppy 8139too 8139cp
[   38.059704] Pid: 1564, comm: pty_kill Tainted: G        W    3.7.0-next-20121130+ttydebug-xeon #20121130+ttydebug
[   38.061578] Call Trace:
[   38.062491]  [&lt;ffffffff81058b4f&gt;] warn_slowpath_common+0x7f/0xc0
[   38.063448]  [&lt;ffffffff81058baa&gt;] warn_slowpath_null+0x1a/0x20
[   38.064439]  [&lt;ffffffff8142dc2b&gt;] n_tty_set_room.part.6+0x8b/0xa0
[   38.065381]  [&lt;ffffffff8142dc82&gt;] n_tty_set_room+0x42/0x80
[   38.066323]  [&lt;ffffffff8142e6f2&gt;] reset_buffer_flags+0x102/0x160
[   38.077508]  [&lt;ffffffff8142e76d&gt;] n_tty_flush_buffer+0x1d/0x90
[   38.078782]  [&lt;ffffffff81046569&gt;] ? default_spin_lock_flags+0x9/0x10
[   38.079734]  [&lt;ffffffff8142e804&gt;] n_tty_close+0x24/0x60
[   38.080730]  [&lt;ffffffff81431b61&gt;] tty_ldisc_close.isra.2+0x41/0x60
[   38.081680]  [&lt;ffffffff81431bbb&gt;] tty_ldisc_kill+0x3b/0x80
[   38.082618]  [&lt;ffffffff81432a07&gt;] tty_ldisc_release+0x77/0xe0
[   38.083549]  [&lt;ffffffff8142b781&gt;] tty_release+0x451/0x4d0
[   38.084525]  [&lt;ffffffff811950be&gt;] __fput+0xae/0x230
[   38.085472]  [&lt;ffffffff8119524e&gt;] ____fput+0xe/0x10
[   38.086401]  [&lt;ffffffff8107aa88&gt;] task_work_run+0xc8/0xf0
[   38.087334]  [&lt;ffffffff8105ea56&gt;] do_exit+0x196/0x4b0
[   38.088304]  [&lt;ffffffff8106c77b&gt;] ? __dequeue_signal+0x6b/0xb0
[   38.089240]  [&lt;ffffffff8105ef34&gt;] do_group_exit+0x44/0xa0
[   38.090182]  [&lt;ffffffff8106f43d&gt;] get_signal_to_deliver+0x20d/0x4e0
[   38.091125]  [&lt;ffffffff81016979&gt;] do_signal+0x29/0x130
[   38.092096]  [&lt;ffffffff81431a9e&gt;] ? tty_ldisc_deref+0xe/0x10
[   38.093030]  [&lt;ffffffff8142a317&gt;] ? tty_write+0xb7/0xf0
[   38.093976]  [&lt;ffffffff81193f53&gt;] ? vfs_write+0xb3/0x180
[   38.094904]  [&lt;ffffffff81016b20&gt;] do_notify_resume+0x80/0xc0
[   38.095830]  [&lt;ffffffff81700492&gt;] int_signal+0x12/0x17
[   38.096788] ---[ end trace 5f6f7a9651cd999b ]---

[ 2730.570602] ------------[ cut here ]------------
[ 2730.572130] WARNING: at drivers/tty/n_tty.c:160 n_tty_set_room+0x107/0x140()
[ 2730.574904] scheduling buffer work for halted ldisc
[ 2730.578303] Pid: 9691, comm: trinity-child15 Tainted: G        W 3.7.0-rc8-next-20121205-sasha-00023-g59f0d85 #207
[ 2730.588694] Call Trace:
[ 2730.590486]  [&lt;ffffffff81c41d77&gt;] ? n_tty_set_room+0x107/0x140
[ 2730.592559]  [&lt;ffffffff8110c827&gt;] warn_slowpath_common+0x87/0xb0
[ 2730.595317]  [&lt;ffffffff8110c8b1&gt;] warn_slowpath_fmt+0x41/0x50
[ 2730.599186]  [&lt;ffffffff81c41d77&gt;] n_tty_set_room+0x107/0x140
[ 2730.603141]  [&lt;ffffffff81c42fe7&gt;] reset_buffer_flags+0x137/0x150
[ 2730.607166]  [&lt;ffffffff81c43018&gt;] n_tty_flush_buffer+0x18/0x90
[ 2730.610123]  [&lt;ffffffff81c430af&gt;] n_tty_close+0x1f/0x60
[ 2730.612068]  [&lt;ffffffff81c461f2&gt;] tty_ldisc_close.isra.4+0x52/0x60
[ 2730.614078]  [&lt;ffffffff81c462ab&gt;] tty_ldisc_reinit+0x3b/0x70
[ 2730.615891]  [&lt;ffffffff81c46db2&gt;] tty_ldisc_hangup+0x102/0x1e0
[ 2730.617780]  [&lt;ffffffff81c3e537&gt;] __tty_hangup+0x137/0x440
[ 2730.619547]  [&lt;ffffffff81c3e869&gt;] tty_vhangup+0x9/0x10
[ 2730.621266]  [&lt;ffffffff81c48f1c&gt;] pty_close+0x14c/0x160
[ 2730.622952]  [&lt;ffffffff81c3fd45&gt;] tty_release+0xd5/0x490
[ 2730.624674]  [&lt;ffffffff8127fbe2&gt;] __fput+0x122/0x250
[ 2730.626195]  [&lt;ffffffff8127fd19&gt;] ____fput+0x9/0x10
[ 2730.627758]  [&lt;ffffffff81134602&gt;] task_work_run+0xb2/0xf0
[ 2730.629491]  [&lt;ffffffff811139ad&gt;] do_exit+0x36d/0x580
[ 2730.631159]  [&lt;ffffffff81113c8a&gt;] do_group_exit+0x8a/0xc0
[ 2730.632819]  [&lt;ffffffff81127351&gt;] get_signal_to_deliver+0x501/0x5b0
[ 2730.634758]  [&lt;ffffffff8106de34&gt;] do_signal+0x24/0x100
[ 2730.636412]  [&lt;ffffffff81204865&gt;] ? user_exit+0xa5/0xd0
[ 2730.638078]  [&lt;ffffffff81183cd8&gt;] ? trace_hardirqs_on_caller+0x118/0x140
[ 2730.640279]  [&lt;ffffffff81183d0d&gt;] ? trace_hardirqs_on+0xd/0x10
[ 2730.642164]  [&lt;ffffffff8106df78&gt;] do_notify_resume+0x48/0xa0
[ 2730.643966]  [&lt;ffffffff83cdff6a&gt;] int_signal+0x12/0x17
[ 2730.645672] ---[ end trace a40d53149c07fce0 ]---

/*
 * pty_thrash.c
 *
 * Based on original test jig by Ilya Zykov &lt;ilya@ilyx.ru&gt;
 *
 * Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
 * Signed-off-by: Ilya Zykov &lt;ilya@ilyx.ru&gt;
 */

static int fd;

static void error_exit(char *f, ...)
{
        va_list va;

        va_start(va, f);
        vprintf(f, va);
        printf(": %s\n", strerror(errno));
        va_end(va);

        if (fd &gt;= 0)
                close(fd);

        exit(EXIT_FAILURE);
}

int main(int argc, char *argv[]) {
        int parent;
        char pts_name[24];
        int ptn, unlock;

        while (1) {

                fd = open("/dev/ptmx", O_RDWR);
                if (fd &lt; 0)
                        error_exit("opening pty master");
                unlock = 0;
                if (ioctl(fd, TIOCSPTLCK, &amp;unlock) &lt; 0)
                        error_exit("unlocking pty pair");
                if (ioctl(fd, TIOCGPTN, &amp;ptn) &lt; 0)
                        error_exit("getting pty #");
                snprintf(pts_name, sizeof(pts_name), "/dev/pts/%d", ptn);

                child_id = fork();
                if (child_id == -1)
                        error_exit("forking child");

                if (parent) {
                        int err, id, status;
                        char buf[128];
                        int n;

                        n = read(fd, buf, sizeof(buf));
                        if (n &lt; 0)
                                error_exit("master reading");
                        printf("%.*s\n", n-1, buf);

                        close(fd);

                        err = kill(child_id, SIGKILL);
                        if (err &lt; 0)
                                error_exit("killing child");
                        id = waitpid(child_id, &amp;status, 0);
                        if (id &lt; 0 || id != child_id)
                                error_exit("waiting for child");

                } else { /* Child */

                        close(fd);
                        printf("Test cycle on slave pty %s\n", pts_name);
                        fd = open(pts_name, O_RDWR);
                        if (fd &lt; 0)
                                error_exit("opening pty slave");

                        while (1) {
                                char pattern[] = "test\n";
                                if (write(fd, pattern, strlen(pattern)) &lt; 0)
                                        error_exit("slave writing");
                        }

                }
        }

        /* never gets here */
        return 0;
}

Reported-by: Sasha Levin &lt;levinsasha928@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>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
A buffer flush is both undesirable and unnecessary when the ldisc
is closing. A buffer flush performs the following:
 1. resets ldisc data fields to their initial state
 2. resets tty-&gt;receive_room to indicate more data can be sent
 3. schedules buffer work to receive more data
 4. signals a buffer flush has happened to linked pty in packet mode

Since the ldisc has been halted and the tty may soon be destructed,
buffer work must not be scheduled as that work might access
an invalid tty and ldisc state. Also, the ldisc read buffer is about
to be freed, so that's pointless.

Resetting the ldisc data fields is pointless as well since that
structure is about to be freed.

Resetting tty-&gt;receive_room is unnecessary, as it will be properly
reset if a new ldisc is reopened. Besides, resetting the original
receive_room value would be wrong since the read buffer will be
gone.

Since the packet mode flush is observable from userspace, this
behavior has been preserved.

The test jig originally authored by Ilya Zykov &lt;ilya@ilyx.ru&gt; and
signed off by him is included below. The test jig prompts the
following warnings which this patch fixes.

[   38.051111] ------------[ cut here ]------------
[   38.052113] WARNING: at drivers/tty/n_tty.c:160 n_tty_set_room.part.6+0x8b/0xa0()
[   38.053916] Hardware name: Bochs
[   38.054819] Modules linked in: netconsole configfs bnep rfcomm bluetooth parport_pc ppdev snd_hda_intel snd_hda_codec
snd_hwdep snd_pcm snd_seq_midi snd_rawmidi snd_seq_midi_event snd_seq psmouse snd_timer serio_raw mac_hid snd_seq_device
snd microcode lp parport virtio_balloon soundcore i2c_piix4 snd_page_alloc floppy 8139too 8139cp
[   38.059704] Pid: 1564, comm: pty_kill Tainted: G        W    3.7.0-next-20121130+ttydebug-xeon #20121130+ttydebug
[   38.061578] Call Trace:
[   38.062491]  [&lt;ffffffff81058b4f&gt;] warn_slowpath_common+0x7f/0xc0
[   38.063448]  [&lt;ffffffff81058baa&gt;] warn_slowpath_null+0x1a/0x20
[   38.064439]  [&lt;ffffffff8142dc2b&gt;] n_tty_set_room.part.6+0x8b/0xa0
[   38.065381]  [&lt;ffffffff8142dc82&gt;] n_tty_set_room+0x42/0x80
[   38.066323]  [&lt;ffffffff8142e6f2&gt;] reset_buffer_flags+0x102/0x160
[   38.077508]  [&lt;ffffffff8142e76d&gt;] n_tty_flush_buffer+0x1d/0x90
[   38.078782]  [&lt;ffffffff81046569&gt;] ? default_spin_lock_flags+0x9/0x10
[   38.079734]  [&lt;ffffffff8142e804&gt;] n_tty_close+0x24/0x60
[   38.080730]  [&lt;ffffffff81431b61&gt;] tty_ldisc_close.isra.2+0x41/0x60
[   38.081680]  [&lt;ffffffff81431bbb&gt;] tty_ldisc_kill+0x3b/0x80
[   38.082618]  [&lt;ffffffff81432a07&gt;] tty_ldisc_release+0x77/0xe0
[   38.083549]  [&lt;ffffffff8142b781&gt;] tty_release+0x451/0x4d0
[   38.084525]  [&lt;ffffffff811950be&gt;] __fput+0xae/0x230
[   38.085472]  [&lt;ffffffff8119524e&gt;] ____fput+0xe/0x10
[   38.086401]  [&lt;ffffffff8107aa88&gt;] task_work_run+0xc8/0xf0
[   38.087334]  [&lt;ffffffff8105ea56&gt;] do_exit+0x196/0x4b0
[   38.088304]  [&lt;ffffffff8106c77b&gt;] ? __dequeue_signal+0x6b/0xb0
[   38.089240]  [&lt;ffffffff8105ef34&gt;] do_group_exit+0x44/0xa0
[   38.090182]  [&lt;ffffffff8106f43d&gt;] get_signal_to_deliver+0x20d/0x4e0
[   38.091125]  [&lt;ffffffff81016979&gt;] do_signal+0x29/0x130
[   38.092096]  [&lt;ffffffff81431a9e&gt;] ? tty_ldisc_deref+0xe/0x10
[   38.093030]  [&lt;ffffffff8142a317&gt;] ? tty_write+0xb7/0xf0
[   38.093976]  [&lt;ffffffff81193f53&gt;] ? vfs_write+0xb3/0x180
[   38.094904]  [&lt;ffffffff81016b20&gt;] do_notify_resume+0x80/0xc0
[   38.095830]  [&lt;ffffffff81700492&gt;] int_signal+0x12/0x17
[   38.096788] ---[ end trace 5f6f7a9651cd999b ]---

[ 2730.570602] ------------[ cut here ]------------
[ 2730.572130] WARNING: at drivers/tty/n_tty.c:160 n_tty_set_room+0x107/0x140()
[ 2730.574904] scheduling buffer work for halted ldisc
[ 2730.578303] Pid: 9691, comm: trinity-child15 Tainted: G        W 3.7.0-rc8-next-20121205-sasha-00023-g59f0d85 #207
[ 2730.588694] Call Trace:
[ 2730.590486]  [&lt;ffffffff81c41d77&gt;] ? n_tty_set_room+0x107/0x140
[ 2730.592559]  [&lt;ffffffff8110c827&gt;] warn_slowpath_common+0x87/0xb0
[ 2730.595317]  [&lt;ffffffff8110c8b1&gt;] warn_slowpath_fmt+0x41/0x50
[ 2730.599186]  [&lt;ffffffff81c41d77&gt;] n_tty_set_room+0x107/0x140
[ 2730.603141]  [&lt;ffffffff81c42fe7&gt;] reset_buffer_flags+0x137/0x150
[ 2730.607166]  [&lt;ffffffff81c43018&gt;] n_tty_flush_buffer+0x18/0x90
[ 2730.610123]  [&lt;ffffffff81c430af&gt;] n_tty_close+0x1f/0x60
[ 2730.612068]  [&lt;ffffffff81c461f2&gt;] tty_ldisc_close.isra.4+0x52/0x60
[ 2730.614078]  [&lt;ffffffff81c462ab&gt;] tty_ldisc_reinit+0x3b/0x70
[ 2730.615891]  [&lt;ffffffff81c46db2&gt;] tty_ldisc_hangup+0x102/0x1e0
[ 2730.617780]  [&lt;ffffffff81c3e537&gt;] __tty_hangup+0x137/0x440
[ 2730.619547]  [&lt;ffffffff81c3e869&gt;] tty_vhangup+0x9/0x10
[ 2730.621266]  [&lt;ffffffff81c48f1c&gt;] pty_close+0x14c/0x160
[ 2730.622952]  [&lt;ffffffff81c3fd45&gt;] tty_release+0xd5/0x490
[ 2730.624674]  [&lt;ffffffff8127fbe2&gt;] __fput+0x122/0x250
[ 2730.626195]  [&lt;ffffffff8127fd19&gt;] ____fput+0x9/0x10
[ 2730.627758]  [&lt;ffffffff81134602&gt;] task_work_run+0xb2/0xf0
[ 2730.629491]  [&lt;ffffffff811139ad&gt;] do_exit+0x36d/0x580
[ 2730.631159]  [&lt;ffffffff81113c8a&gt;] do_group_exit+0x8a/0xc0
[ 2730.632819]  [&lt;ffffffff81127351&gt;] get_signal_to_deliver+0x501/0x5b0
[ 2730.634758]  [&lt;ffffffff8106de34&gt;] do_signal+0x24/0x100
[ 2730.636412]  [&lt;ffffffff81204865&gt;] ? user_exit+0xa5/0xd0
[ 2730.638078]  [&lt;ffffffff81183cd8&gt;] ? trace_hardirqs_on_caller+0x118/0x140
[ 2730.640279]  [&lt;ffffffff81183d0d&gt;] ? trace_hardirqs_on+0xd/0x10
[ 2730.642164]  [&lt;ffffffff8106df78&gt;] do_notify_resume+0x48/0xa0
[ 2730.643966]  [&lt;ffffffff83cdff6a&gt;] int_signal+0x12/0x17
[ 2730.645672] ---[ end trace a40d53149c07fce0 ]---

/*
 * pty_thrash.c
 *
 * Based on original test jig by Ilya Zykov &lt;ilya@ilyx.ru&gt;
 *
 * Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
 * Signed-off-by: Ilya Zykov &lt;ilya@ilyx.ru&gt;
 */

static int fd;

static void error_exit(char *f, ...)
{
        va_list va;

        va_start(va, f);
        vprintf(f, va);
        printf(": %s\n", strerror(errno));
        va_end(va);

        if (fd &gt;= 0)
                close(fd);

        exit(EXIT_FAILURE);
}

int main(int argc, char *argv[]) {
        int parent;
        char pts_name[24];
        int ptn, unlock;

        while (1) {

                fd = open("/dev/ptmx", O_RDWR);
                if (fd &lt; 0)
                        error_exit("opening pty master");
                unlock = 0;
                if (ioctl(fd, TIOCSPTLCK, &amp;unlock) &lt; 0)
                        error_exit("unlocking pty pair");
                if (ioctl(fd, TIOCGPTN, &amp;ptn) &lt; 0)
                        error_exit("getting pty #");
                snprintf(pts_name, sizeof(pts_name), "/dev/pts/%d", ptn);

                child_id = fork();
                if (child_id == -1)
                        error_exit("forking child");

                if (parent) {
                        int err, id, status;
                        char buf[128];
                        int n;

                        n = read(fd, buf, sizeof(buf));
                        if (n &lt; 0)
                                error_exit("master reading");
                        printf("%.*s\n", n-1, buf);

                        close(fd);

                        err = kill(child_id, SIGKILL);
                        if (err &lt; 0)
                                error_exit("killing child");
                        id = waitpid(child_id, &amp;status, 0);
                        if (id &lt; 0 || id != child_id)
                                error_exit("waiting for child");

                } else { /* Child */

                        close(fd);
                        printf("Test cycle on slave pty %s\n", pts_name);
                        fd = open(pts_name, O_RDWR);
                        if (fd &lt; 0)
                                error_exit("opening pty slave");

                        while (1) {
                                char pattern[] = "test\n";
                                if (write(fd, pattern, strlen(pattern)) &lt; 0)
                                        error_exit("slave writing");
                        }

                }
        }

        /* never gets here */
        return 0;
}

Reported-by: Sasha Levin &lt;levinsasha928@gmail.com&gt;
Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>n_tty: Factor packet mode status change for reuse</title>
<updated>2013-03-18T23:32:46+00:00</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2013-03-11T20:44:22+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=a30737ab7d99f27810b254787e5e62a6c92cb355'/>
<id>a30737ab7d99f27810b254787e5e62a6c92cb355</id>
<content type='text'>
Factor the packet mode status change from n_tty_flush_buffer
for use by follow-on patch.

Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Factor the packet mode status change from n_tty_flush_buffer
for use by follow-on patch.

Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>tty: Add diagnostic for halted line discipline</title>
<updated>2013-03-18T23:32:46+00:00</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2013-03-11T20:44:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=21622939fc452c7fb739464b8e49368c3ceaa0ee'/>
<id>21622939fc452c7fb739464b8e49368c3ceaa0ee</id>
<content type='text'>
Flip buffer work must not be scheduled by the line discipline
after the line discipline has been halted; issue warning.

Note: drivers can still schedule flip buffer work.

Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Flip buffer work must not be scheduled by the line discipline
after the line discipline has been halted; issue warning.

Note: drivers can still schedule flip buffer work.

Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>n_tty: Lock access to tty-&gt;pgrp for POSIX job control</title>
<updated>2013-03-18T23:13:59+00:00</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2013-03-06T13:38:20+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=01a5e440c91dc6065cf3dbc38aa7276fc4ce2f26'/>
<id>01a5e440c91dc6065cf3dbc38aa7276fc4ce2f26</id>
<content type='text'>
Concurrent access to tty-&gt;pgrp must be protected with tty-&gt;ctrl_lock.
Also, as noted in the comments, reading current-&gt;signal-&gt;tty is
safe because either,
  1) current-&gt;signal-&gt;tty is assigned by current, or
  2) current-&gt;signal-&gt;tty is set to NULL.

NB: for reference, tty_check_change() implements a similar POSIX
check for the ioctls corresponding to tcflush(), tcdrain(),
tcsetattr(), tcsetpgrp(), tcflow() and tcsendbreak().

Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Concurrent access to tty-&gt;pgrp must be protected with tty-&gt;ctrl_lock.
Also, as noted in the comments, reading current-&gt;signal-&gt;tty is
safe because either,
  1) current-&gt;signal-&gt;tty is assigned by current, or
  2) current-&gt;signal-&gt;tty is set to NULL.

NB: for reference, tty_check_change() implements a similar POSIX
check for the ioctls corresponding to tcflush(), tcdrain(),
tcsetattr(), tcsetpgrp(), tcflow() and tcsendbreak().

Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>n_tty: Fix unsafe driver-side signals</title>
<updated>2013-03-18T23:13:59+00:00</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2013-03-06T13:38:19+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=8c985d18b136c5d511445d15f0c6650003a8946b'/>
<id>8c985d18b136c5d511445d15f0c6650003a8946b</id>
<content type='text'>
An ldisc reference is insufficient guarantee the foreground process
group is not in the process of being signalled from a hangup.

1) Reads of tty-&gt;pgrp must be locked with ctrl_lock
2) The group pid must be referenced for the duration of signalling.
   Because the driver-side is not process-context, a pid reference
   must be acquired.

Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
An ldisc reference is insufficient guarantee the foreground process
group is not in the process of being signalled from a hangup.

1) Reads of tty-&gt;pgrp must be locked with ctrl_lock
2) The group pid must be referenced for the duration of signalling.
   Because the driver-side is not process-context, a pid reference
   must be acquired.

Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>n_tty: Fix stuck throttled driver</title>
<updated>2013-03-18T23:11:59+00:00</updated>
<author>
<name>Peter Hurley</name>
<email>peter@hurleysoftware.com</email>
</author>
<published>2013-03-06T13:20:53+00:00</published>
<link rel='alternate' type='text/html' href='https://git.toradex.cn/cgit/linux-toradex.git/commit/?id=e91e52e42814b130c20d17bc1e2adf813c50db11'/>
<id>e91e52e42814b130c20d17bc1e2adf813c50db11</id>
<content type='text'>
As noted in the following comment:

  /* FIXME: there is a tiny race here if the receive room check runs
     before the other work executes and empties the buffer (upping
     the receiving room and unthrottling. We then throttle and get
     stuck. This has been observed and traced down by Vincent Pillet/
     We need to address this when we sort out out the rx path locking */

Use new safe throttle/unthrottle functions to re-evaluate conditions
if interrupted by the complement flow control function.

Reported-by: Vincent Pillet &lt;vincentx.pillet@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>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
As noted in the following comment:

  /* FIXME: there is a tiny race here if the receive room check runs
     before the other work executes and empties the buffer (upping
     the receiving room and unthrottling. We then throttle and get
     stuck. This has been observed and traced down by Vincent Pillet/
     We need to address this when we sort out out the rx path locking */

Use new safe throttle/unthrottle functions to re-evaluate conditions
if interrupted by the complement flow control function.

Reported-by: Vincent Pillet &lt;vincentx.pillet@intel.com&gt;
Signed-off-by: Peter Hurley &lt;peter@hurleysoftware.com&gt;
Signed-off-by: Greg Kroah-Hartman &lt;gregkh@linuxfoundation.org&gt;
</pre>
</div>
</content>
</entry>
</feed>
