aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial/ftdi_sio.c
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2013-02-13 11:53:28 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-02-13 12:20:06 -0500
commitb2ca699076573c94fee9a73cb0d8645383b602a0 (patch)
treeb9579ce8ed1511a5b3a234b03392b3c095de9231 /drivers/usb/serial/ftdi_sio.c
parentcd565279e51bedee1b2988e84f9b3bef485adeb6 (diff)
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/ftdi_sio.c')
-rw-r--r--drivers/usb/serial/ftdi_sio.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 90ceef1776c3..d07fccf3bab5 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1886,24 +1886,22 @@ static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
1886{ 1886{
1887 struct ftdi_private *priv = usb_get_serial_port_data(port); 1887 struct ftdi_private *priv = usb_get_serial_port_data(port);
1888 1888
1889 mutex_lock(&port->serial->disc_mutex); 1889 /* Disable flow control */
1890 if (!port->serial->disconnected) { 1890 if (!on) {
1891 /* Disable flow control */ 1891 if (usb_control_msg(port->serial->dev,
1892 if (!on && usb_control_msg(port->serial->dev,
1893 usb_sndctrlpipe(port->serial->dev, 0), 1892 usb_sndctrlpipe(port->serial->dev, 0),
1894 FTDI_SIO_SET_FLOW_CTRL_REQUEST, 1893 FTDI_SIO_SET_FLOW_CTRL_REQUEST,
1895 FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 1894 FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
1896 0, priv->interface, NULL, 0, 1895 0, priv->interface, NULL, 0,
1897 WDR_TIMEOUT) < 0) { 1896 WDR_TIMEOUT) < 0) {
1898 dev_err(&port->dev, "error from flowcontrol urb\n"); 1897 dev_err(&port->dev, "error from flowcontrol urb\n");
1899 } 1898 }
1900 /* drop RTS and DTR */
1901 if (on)
1902 set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
1903 else
1904 clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
1905 } 1899 }
1906 mutex_unlock(&port->serial->disc_mutex); 1900 /* drop RTS and DTR */
1901 if (on)
1902 set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
1903 else
1904 clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
1907} 1905}
1908 1906
1909/* 1907/*