diff options
author | Johan Hovold <jhovold@gmail.com> | 2013-02-13 11:53:28 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-02-13 12:20:06 -0500 |
commit | b2ca699076573c94fee9a73cb0d8645383b602a0 (patch) | |
tree | b9579ce8ed1511a5b3a234b03392b3c095de9231 /drivers/usb/serial/sierra.c | |
parent | cd565279e51bedee1b2988e84f9b3bef485adeb6 (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/sierra.c')
-rw-r--r-- | drivers/usb/serial/sierra.c | 8 |
1 files changed, 1 insertions, 7 deletions
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index af06f2f5f38b..d4426c038c32 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
@@ -861,19 +861,13 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
861 | 861 | ||
862 | static void sierra_dtr_rts(struct usb_serial_port *port, int on) | 862 | static void sierra_dtr_rts(struct usb_serial_port *port, int on) |
863 | { | 863 | { |
864 | struct usb_serial *serial = port->serial; | ||
865 | struct sierra_port_private *portdata; | 864 | struct sierra_port_private *portdata; |
866 | 865 | ||
867 | portdata = usb_get_serial_port_data(port); | 866 | portdata = usb_get_serial_port_data(port); |
868 | portdata->rts_state = on; | 867 | portdata->rts_state = on; |
869 | portdata->dtr_state = on; | 868 | portdata->dtr_state = on; |
870 | 869 | ||
871 | if (serial->dev) { | 870 | sierra_send_setup(port); |
872 | mutex_lock(&serial->disc_mutex); | ||
873 | if (!serial->disconnected) | ||
874 | sierra_send_setup(port); | ||
875 | mutex_unlock(&serial->disc_mutex); | ||
876 | } | ||
877 | } | 871 | } |
878 | 872 | ||
879 | static int sierra_startup(struct usb_serial *serial) | 873 | static int sierra_startup(struct usb_serial *serial) |