aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/serial
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2009-07-27 05:58:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-07-27 15:23:22 -0400
commitb68f2fb9e73f46037fbeca5fbd4ae8a7ddd8ef6b (patch)
tree1149afd6c48dcb408f01e75ad250165522693188 /drivers/usb/serial
parent6a31d4aeab85a02f9a57ca37b935054393daa794 (diff)
tty: Fix a USB serial crash/scribble
The port lock is used to protect the port state. However the port structure is freed on a hangup, then the lock taken on a close. The right fix is to drop the port on tty->shutdown() but we can't yet do that due to sleep v non-sleeping rules. Instead do the next best thing and fix it up when we are not in -rc season. Reported-by: Daniel Mack <daniel@caiaq.de> Signed-off-by: Alan Cox <alan@linux.intel.com> Tested-by: Daniel Mack <daniel@caiaq.de> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/usb/serial')
-rw-r--r--drivers/usb/serial/usb-serial.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index bd7581b3a48a..3c8923f62ed1 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -340,6 +340,22 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
340 340
341 dbg("%s - port %d", __func__, port->number); 341 dbg("%s - port %d", __func__, port->number);
342 342
343 /* FIXME:
344 This leaves a very narrow race. Really we should do the
345 serial_do_free() on tty->shutdown(), but tty->shutdown can
346 be called from IRQ context and serial_do_free can sleep.
347
348 The right fix is probably to make the tty free (which is rare)
349 and thus tty->shutdown() occur via a work queue and simplify all
350 the drivers that use it.
351 */
352 if (tty_hung_up_p(filp)) {
353 /* serial_hangup already called serial_down at this point.
354 Another user may have already reopened the port but
355 serial_do_free is refcounted */
356 serial_do_free(port);
357 return;
358 }
343 359
344 if (tty_port_close_start(&port->port, tty, filp) == 0) 360 if (tty_port_close_start(&port->port, tty, filp) == 0)
345 return; 361 return;
@@ -355,7 +371,8 @@ static void serial_hangup(struct tty_struct *tty)
355 struct usb_serial_port *port = tty->driver_data; 371 struct usb_serial_port *port = tty->driver_data;
356 serial_do_down(port); 372 serial_do_down(port);
357 tty_port_hangup(&port->port); 373 tty_port_hangup(&port->port);
358 serial_do_free(port); 374 /* We must not free port yet - the USB serial layer depends on it's
375 continued existence */
359} 376}
360 377
361static int serial_write(struct tty_struct *tty, const unsigned char *buf, 378static int serial_write(struct tty_struct *tty, const unsigned char *buf,