From: Peter Hurley Date: Wed, 20 Mar 2013 17:20:43 +0000 (-0400) Subject: tty: Fix race condition if flushing tty flip buffers X-Git-Tag: omap-for-v3.10/dt-fixes-for-merge-window~136^2~28 X-Git-Url: http://git.openpandora.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=39f610e40eecc39e4c34e047fd6904ca6b525520;p=pandora-kernel.git 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 Signed-off-by: Peter Hurley Acked-by: Ilya Zykov Cc: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- Reading git-diff-tree failed