[3.19.y-ckt stable] Patch "serial: core: Fix crashes while echoing when closing" has been added to staging queue

Kamal Mostafa kamal at canonical.com
Thu Aug 27 22:08:24 UTC 2015


This is a note to let you know that I have just added a patch titled

    serial: core: Fix crashes while echoing when closing

to the linux-3.19.y-queue branch of the 3.19.y-ckt extended stable tree 
which can be found at:

    http://kernel.ubuntu.com/git/ubuntu/linux.git/log/?h=linux-3.19.y-queue

This patch is scheduled to be released in version 3.19.8-ckt6.

If you, or anyone else, feels it should not be added to this tree, please 
reply to this email.

For more information about the 3.19.y-ckt tree, see
https://wiki.ubuntu.com/Kernel/Dev/ExtendedStable

Thanks.
-Kamal

------

>From ccfe62c48b9afb5c97618a9cf72029fd951bfb13 Mon Sep 17 00:00:00 2001
From: Peter Hurley <peter at hurleysoftware.com>
Date: Sun, 12 Jul 2015 21:05:26 -0400
Subject: serial: core: Fix crashes while echoing when closing

commit e144c58cad6667876173dd76977e9e6557e34941 upstream.

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 at hp.com>
Signed-off-by: Peter Hurley <peter at hurleysoftware.com>
Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>

Signed-off-by: Kamal Mostafa <kamal at canonical.com>
---
 drivers/tty/serial/serial_core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 984605b..86f6d8b 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -1429,7 +1429,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
 	mutex_lock(&port->mutex);
 	uart_shutdown(tty, state);
 	tty_port_tty_set(port, NULL);
-	tty->closing = 0;
+
 	spin_lock_irqsave(&port->lock, flags);

 	if (port->blocked_open) {
@@ -1455,6 +1455,7 @@ static void uart_close(struct tty_struct *tty, struct file *filp)
 	mutex_unlock(&port->mutex);

 	tty_ldisc_flush(tty);
+	tty->closing = 0;
 }

 static void uart_wait_until_sent(struct tty_struct *tty, int timeout)
--
1.9.1





More information about the kernel-team mailing list