Prepare uart_poll_init() to safely dereference uart port; expand the port mutex section to guarantee uart port remains valid until uart_poll_init() completes.
Signed-off-by: Peter Hurley <[email protected]> --- drivers/tty/serial/serial_core.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c index 806eba81..16c4c48 100644 --- a/drivers/tty/serial/serial_core.c +++ b/drivers/tty/serial/serial_core.c @@ -2268,42 +2268,41 @@ static int uart_poll_init(struct tty_driver *driver, int line, char *options) { struct uart_driver *drv = driver->driver_state; struct uart_state *state = drv->state + line; - struct uart_port *port; + struct tty_port *port; + struct uart_port *uport; int baud = 9600; int bits = 8; int parity = 'n'; int flow = 'n'; - int ret; + int ret = -1; - if (!state || !state->uart_port) + if (!state) return -1; - port = state->uart_port; - if (!(port->ops->poll_get_char && port->ops->poll_put_char)) - return -1; + port = &state->port; + mutex_lock(&port->mutex); - if (port->ops->poll_init) { - struct tty_port *tport = &state->port; + uport = state->uart_port; + if (!(uport->ops->poll_get_char && uport->ops->poll_put_char)) + goto out; - ret = 0; - mutex_lock(&tport->mutex); + ret = 0; + if (uport->ops->poll_init) { /* * We don't set ASYNCB_INITIALIZED as we only initialized the * hw, e.g. state->xmit is still uninitialized. */ - if (!test_bit(ASYNCB_INITIALIZED, &tport->flags)) - ret = port->ops->poll_init(port); - mutex_unlock(&tport->mutex); - if (ret) - return ret; + if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) + ret = uport->ops->poll_init(uport); } - if (options) { + if (!ret && options) { uart_parse_options(options, &baud, &parity, &bits, &flow); - return uart_set_options(port, NULL, baud, parity, bits, flow); + ret = uart_set_options(uport, NULL, baud, parity, bits, flow); } - - return 0; +out: + mutex_unlock(&port->mutex); + return ret; } static int uart_poll_get_char(struct tty_driver *driver, int line) -- 2.6.3 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/

