From 9ed19428a51d53477e2b79be3303fa08f8575749 Mon Sep 17 00:00:00 2001 From: Peter Hurley Date: Sat, 9 Apr 2016 18:56:34 -0700 Subject: serial: core: Prevent unsafe uart port access, part 2 For serial core operations not already excluded by holding port->mutex, use reference counting to protect deferencing the state->uart_port. Introduce helper functions, uart_port_ref() and uart_port_deref(), to wrap uart_port access, and helper macros, uart_port_lock() and uart_port_unlock(), to wrap combination uart_port access with uart port lock sections. Port removal in uart_remove_one_port() waits for reference count to drop to zero before detaching the uart port from struct uart_state. For functions only reading the tx circular buffer indexes (where the uart port lock is claimed to prevent concurrent users), a NULL uart port is simply ignored and the operation completes normally. For functions change the tx circular buffer indexes (where the uart port lock is claimed to prevent concurrent users), the operation is aborted if the uart port is NULL (ie., has been detached). Signed-off-by: Peter Hurley Signed-off-by: Greg Kroah-Hartman --- include/linux/serial_core.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux/serial_core.h') diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index cbfcf38e220d..fd4ad4dce11a 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -281,6 +281,8 @@ struct uart_state { enum uart_pm_state pm_state; struct circ_buf xmit; + atomic_t refcount; + wait_queue_head_t remove_wait; struct uart_port *uart_port; }; -- cgit From 144ef5c2df9b473dad7eab375adcf5b11d0b1e47 Mon Sep 17 00:00:00 2001 From: Wan Ahmad Zainie Date: Wed, 6 Apr 2016 12:06:51 +0800 Subject: serial: 8250: export get_mctrl function Exposes get_mctrl() function so that it can be overriden with platform specific implementation. Signed-off-by: Wan Ahmad Zainie Reviewed-by: Andy Shevchenko Reviewed-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/tty/serial/8250/8250_core.c | 3 +++ drivers/tty/serial/8250/8250_port.c | 10 +++++++++- include/linux/serial_8250.h | 2 ++ include/linux/serial_core.h | 1 + 4 files changed, 15 insertions(+), 1 deletion(-) (limited to 'include/linux/serial_core.h') diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index 2f4f5ee651db..0fbd7c033a25 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -830,6 +830,7 @@ static int serial8250_probe(struct platform_device *dev) uart.port.handle_irq = p->handle_irq; uart.port.handle_break = p->handle_break; uart.port.set_termios = p->set_termios; + uart.port.get_mctrl = p->get_mctrl; uart.port.pm = p->pm; uart.port.dev = &dev->dev; uart.port.irqflags |= irqflag; @@ -1022,6 +1023,8 @@ int serial8250_register_8250_port(struct uart_8250_port *up) /* Possibly override set_termios call */ if (up->port.set_termios) uart->port.set_termios = up->port.set_termios; + if (up->port.get_mctrl) + uart->port.get_mctrl = up->port.get_mctrl; if (up->port.set_mctrl) uart->port.set_mctrl = up->port.set_mctrl; if (up->port.startup) diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index 00ad2637b08c..a803ddfd5a59 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -1882,7 +1882,7 @@ static unsigned int serial8250_tx_empty(struct uart_port *port) return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0; } -static unsigned int serial8250_get_mctrl(struct uart_port *port) +unsigned int serial8250_do_get_mctrl(struct uart_port *port) { struct uart_8250_port *up = up_to_u8250p(port); unsigned int status; @@ -1903,6 +1903,14 @@ static unsigned int serial8250_get_mctrl(struct uart_port *port) ret |= TIOCM_CTS; return ret; } +EXPORT_SYMBOL_GPL(serial8250_do_get_mctrl); + +static unsigned int serial8250_get_mctrl(struct uart_port *port) +{ + if (port->get_mctrl) + return port->get_mctrl(port); + return serial8250_do_get_mctrl(port); +} void serial8250_do_set_mctrl(struct uart_port *port, unsigned int mctrl) { diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 434879759725..48ec7651989b 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -36,6 +36,7 @@ struct plat_serial8250_port { void (*set_termios)(struct uart_port *, struct ktermios *new, struct ktermios *old); + unsigned int (*get_mctrl)(struct uart_port *); int (*handle_irq)(struct uart_port *); void (*pm)(struct uart_port *, unsigned int state, unsigned old); @@ -148,6 +149,7 @@ extern int early_serial8250_setup(struct earlycon_device *device, const char *options); extern void serial8250_do_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old); +extern unsigned int serial8250_do_get_mctrl(struct uart_port *port); extern int serial8250_do_startup(struct uart_port *port); extern void serial8250_do_shutdown(struct uart_port *port); extern void serial8250_do_pm(struct uart_port *port, unsigned int state, diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index fd4ad4dce11a..a3d7c0d4a03e 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -123,6 +123,7 @@ struct uart_port { void (*set_termios)(struct uart_port *, struct ktermios *new, struct ktermios *old); + unsigned int (*get_mctrl)(struct uart_port *); void (*set_mctrl)(struct uart_port *, unsigned int); int (*startup)(struct uart_port *port); void (*shutdown)(struct uart_port *port); -- cgit