diff options
author | Peter Hurley <peter@hurleysoftware.com> | 2015-07-13 04:05:26 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-07-24 04:08:28 +0300 |
commit | e144c58cad6667876173dd76977e9e6557e34941 (patch) | |
tree | 77a8fb4466d880c78ccc913fa29e69fc3aac0f5f /drivers/regulator/dbx500-prcmu.c | |
parent | 7525a9901b5ee3c84933ad069e41506c37404ddc (diff) | |
download | linux-e144c58cad6667876173dd76977e9e6557e34941.tar.xz |
serial: core: Fix crashes while echoing when closing
While closing, new rx data may be received after the input buffers
have been flushed but before stop_rx() halts receiving [1]. The
new data might not be processed by flush_to_ldisc() until after
uart_shutdown() and normal input processing is re-enabled (ie.,
tty->closing = 0). The race is outlined below:
CPU 0 | CPU 1
|
uart_close() |
tty_port_close_start() |
tty->closing = 1 |
tty_ldisc_flush() |
| => IRQ
| while (LSR & data ready)
| uart_insert_char()
| tty_flip_buffer_push()
| <= EOI
stop_rx() | .
uart_shutdown() | .
free xmit.buf | .
tty_port_tty_set(NULL) | .
tty->closing = 0 | .
| flush_to_ldisc()
| n_tty_receive_buf_common()
| __receive_buf()
| ...
| commit_echoes()
| uart_flush_chars()
| __uart_start()
| ** OOPS on port.tty deref **
tty_ldisc_flush() |
Input processing must be prevented from echoing (tty->closing = 1)
until _after_ the input buffers have been flushed again at the end
of uart_close().
[1] In fact, some input may actually be buffered _after_ stop_rx()
since the rx interrupt may have already triggered but not yet been
handled when stop_rx() disables rx interrupts.
Fixes: 2e758910832d ("serial: core: Flush ldisc after dropping port
mutex in uart_close()")
Reported-by: Robert Elliott <elliott@hp.com>
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/regulator/dbx500-prcmu.c')
0 files changed, 0 insertions, 0 deletions