summaryrefslogtreecommitdiff
path: root/drivers/usb/serial/ssu100.c
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2013-02-13 20:53:28 +0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-02-13 21:20:06 +0400
commitb2ca699076573c94fee9a73cb0d8645383b602a0 (patch)
treeb9579ce8ed1511a5b3a234b03392b3c095de9231 /drivers/usb/serial/ssu100.c
parentcd565279e51bedee1b2988e84f9b3bef485adeb6 (diff)
downloadlinux-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/ssu100.c')
-rw-r--r--drivers/usb/serial/ssu100.c19
1 files changed, 8 insertions, 11 deletions
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c
index 4543ea350229..d938396171e8 100644
--- a/drivers/usb/serial/ssu100.c
+++ b/drivers/usb/serial/ssu100.c
@@ -506,19 +506,16 @@ static void ssu100_dtr_rts(struct usb_serial_port *port, int on)
{
struct usb_device *dev = port->serial->dev;
- mutex_lock(&port->serial->disc_mutex);
- if (!port->serial->disconnected) {
- /* Disable flow control */
- if (!on &&
- ssu100_setregister(dev, 0, UART_MCR, 0) < 0)
+ /* Disable flow control */
+ if (!on) {
+ if (ssu100_setregister(dev, 0, UART_MCR, 0) < 0)
dev_err(&port->dev, "error from flowcontrol urb\n");
- /* drop RTS and DTR */
- if (on)
- set_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
- else
- clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
}
- mutex_unlock(&port->serial->disc_mutex);
+ /* drop RTS and DTR */
+ if (on)
+ set_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
+ else
+ clear_mctrl(dev, TIOCM_DTR | TIOCM_RTS);
}
static void ssu100_update_msr(struct usb_serial_port *port, u8 msr)