diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2014-05-02 10:56:12 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-05-03 18:14:28 -0400 |
commit | 62a0d8d7c2b29f92850e4ee3c38e5dfd936e92b2 (patch) | |
tree | ba32a5252d3cbfb5603da1d6391917415fb77b6b /lib/dynamic_queue_limits.c | |
parent | 5fbf1a65dd53ef313783c34a0e93a6e29def6136 (diff) | |
download | linux-62a0d8d7c2b29f92850e4ee3c38e5dfd936e92b2.tar.bz2 |
tty: Fix lockless tty buffer race
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->commit - head->read
n = tty_buffer_alloc() |
b->commit = b->used |
b->next = n |
| if (!count) /* T */
| if (head->next == NULL) /* F */
| buf->head = head->next
In this case, buf->head has been advanced but head->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 <manfred.schlaegl@gmx.at>
Cc: <stable@vger.kernel.org> # 3.12.x+
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'lib/dynamic_queue_limits.c')
0 files changed, 0 insertions, 0 deletions