diff options
author | Johan Hovold <jhovold@gmail.com> | 2013-02-13 20:53:28 +0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-02-13 21:20:06 +0400 |
commit | b2ca699076573c94fee9a73cb0d8645383b602a0 (patch) | |
tree | b9579ce8ed1511a5b3a234b03392b3c095de9231 /drivers/usb/serial/quatech2.c | |
parent | cd565279e51bedee1b2988e84f9b3bef485adeb6 (diff) | |
download | linux-b2ca699076573c94fee9a73cb0d8645383b602a0.tar.xz |
USB: serial: fix null-pointer dereferences on disconnect
Make sure serial-driver dtr_rts is called with disc_mutex held after
checking the disconnected flag.
Due to a bug in the tty layer, dtr_rts may get called after a device has
been disconnected and the tty-device unregistered. Some drivers have had
individual checks for disconnect to make sure the disconnected interface
was not accessed, but this should really be handled in usb-serial core
(at least until the long-standing tty-bug has been fixed).
Note that the problem has been made more acute with commit 0998d0631001
("device-core: Ensure drvdata = NULL when no driver is bound") as the
port data is now also NULL when dtr_rts is called resulting in further
oopses.
Reported-by: Chris Ruehl <chris.ruehl@gtsys.com.hk>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <jhovold@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/serial/quatech2.c')
-rw-r--r-- | drivers/usb/serial/quatech2.c | 18 |
1 files changed, 8 insertions, 10 deletions
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index d152be97d041..a8d5110d4cc5 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -945,19 +945,17 @@ static void qt2_dtr_rts(struct usb_serial_port *port, int on) struct usb_device *dev = port->serial->dev; struct qt2_port_private *port_priv = usb_get_serial_port_data(port); - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) { - /* Disable flow control */ - if (!on && qt2_setregister(dev, port_priv->device_port, + /* Disable flow control */ + if (!on) { + if (qt2_setregister(dev, port_priv->device_port, UART_MCR, 0) < 0) dev_warn(&port->dev, "error from flowcontrol urb\n"); - /* drop RTS and DTR */ - if (on) - update_mctrl(port_priv, TIOCM_DTR | TIOCM_RTS, 0); - else - update_mctrl(port_priv, 0, TIOCM_DTR | TIOCM_RTS); } - mutex_unlock(&port->serial->disc_mutex); + /* drop RTS and DTR */ + if (on) + update_mctrl(port_priv, TIOCM_DTR | TIOCM_RTS, 0); + else + update_mctrl(port_priv, 0, TIOCM_DTR | TIOCM_RTS); } static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch) |