diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2013-03-20 13:20:43 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-04-09 17:05:02 -0700 |
commit | 39f610e40eecc39e4c34e047fd6904ca6b525520 (patch) | |
tree | 39af27120456a3a3b68b7068d65a71f5614db008 /drivers/tty/serial | |
parent | 31bdfc649f4577c9b1120c67b7b1e85f7777aad0 (diff) | |
download | op-kernel-dev-39f610e40eecc39e4c34e047fd6904ca6b525520.zip op-kernel-dev-39f610e40eecc39e4c34e047fd6904ca6b525520.tar.gz |
tty: Fix race condition if flushing tty flip buffers
As Ilya Zykov identified in his patch 'PROBLEM: Race condition in
tty buffer's function flush_to_ldisc()', a race condition exists
which allows a parallel flush_to_ldisc() to flush and free the tty
flip buffers while those buffers are in-use. For example,
CPU 0 | CPU 1 | CPU 2
| flush_to_ldisc() |
| grab spin lock |
tty_buffer_flush() | | flush_to_ldisc()
wait for spin lock | | wait for spin lock
| if (!test_and_set_bit(TTYP_FLUSHING)) |
| while (next flip buffer) |
| ... |
| drop spin lock |
grab spin lock | |
if (test_bit(TTYP_FLUSHING)) | |
set_bit(TTYP_FLUSHPENDING) | receive_buf() |
drop spin lock | |
| | grab spin lock
| | if (!test_and_set_bit(TTYP_FLUSHING))
| | if (test_bit(TTYP_FLUSHPENDING))
| | __tty_buffer_flush()
CPU 2 has just flushed and freed all tty flip buffers while CPU 1 is
transferring data from the head flip buffer.
The original patch was rejected under the assumption that parallel
flush_to_ldisc() was not possible. Because of necessary changes to
the workqueue api, work items can execute in parallel on SMP.
This patch differs slightly from the original patch by testing for
a pending flush _after_ each receive_buf(), since TTYP_FLUSHPENDING
can only be set while the lock is dropped around receive_buf().
Reported-by: Ilya Zykov <linux@izyk.ru>
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Acked-by: Ilya Zykov <linux@izyk.ru>
Cc: Jiri Slaby <jslaby@suse.cz>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/serial')
0 files changed, 0 insertions, 0 deletions