|
| 1 | +From c235ccc1c4d6fd8b7d48b976b87416230ffd5149 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Peter Hurley <peter@hurleysoftware.com> |
| 3 | +Date: Tue, 2 Sep 2014 17:39:13 -0400 |
| 4 | +Subject: [PATCH] serial: core: Fix x_char race |
| 5 | + |
| 6 | +The UART driver is expected to clear port->x_char after |
| 7 | +transmission while holding the port->lock. However, the serial |
| 8 | +core fails to take the port->lock before assigning port->xchar. |
| 9 | +This allows for the following race |
| 10 | + |
| 11 | +CPU 0 | CPU 1 |
| 12 | + | |
| 13 | + | serial8250_handle_irq |
| 14 | + | ... |
| 15 | + | serial8250_tx_chars |
| 16 | + | if (port->x_char) |
| 17 | + | serial_out(up, UART_TX, port->x_char) |
| 18 | +uart_send_xchar | |
| 19 | + port->x_char = ch | |
| 20 | + | port->x_char = 0 |
| 21 | + port->ops->start_tx() | |
| 22 | + | |
| 23 | + |
| 24 | +The x_char on CPU 0 will never be sent. |
| 25 | + |
| 26 | +Take the port->lock in uart_send_xchar() before assigning port->x_char. |
| 27 | + |
| 28 | +Signed-off-by: Peter Hurley <peter@hurleysoftware.com> |
| 29 | +Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| 30 | +--- |
| 31 | + drivers/tty/serial/serial_core.c | 7 +++---- |
| 32 | + 1 file changed, 3 insertions(+), 4 deletions(-) |
| 33 | + |
| 34 | +diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c |
| 35 | +index 0742f77ac410..bd20cf51e912 100644 |
| 36 | +--- a/drivers/tty/serial/serial_core.c |
| 37 | ++++ b/drivers/tty/serial/serial_core.c |
| 38 | +@@ -600,12 +600,11 @@ static void uart_send_xchar(struct tty_struct *tty, char ch) |
| 39 | + if (port->ops->send_xchar) |
| 40 | + port->ops->send_xchar(port, ch); |
| 41 | + else { |
| 42 | ++ spin_lock_irqsave(&port->lock, flags); |
| 43 | + port->x_char = ch; |
| 44 | +- if (ch) { |
| 45 | +- spin_lock_irqsave(&port->lock, flags); |
| 46 | ++ if (ch) |
| 47 | + port->ops->start_tx(port); |
| 48 | +- spin_unlock_irqrestore(&port->lock, flags); |
| 49 | +- } |
| 50 | ++ spin_unlock_irqrestore(&port->lock, flags); |
| 51 | + } |
| 52 | + } |
| 53 | + |
| 54 | +-- |
| 55 | +2.17.1 |
| 56 | + |
0 commit comments