forked from luck/tmp_suning_uos_patched
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>
This commit is contained in:
parent
6a31d4aeab
commit
b68f2fb9e7
@ -340,6 +340,22 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
|
||||
|
||||
dbg("%s - port %d", __func__, port->number);
|
||||
|
||||
/* FIXME:
|
||||
This leaves a very narrow race. Really we should do the
|
||||
serial_do_free() on tty->shutdown(), but tty->shutdown can
|
||||
be called from IRQ context and serial_do_free can sleep.
|
||||
|
||||
The right fix is probably to make the tty free (which is rare)
|
||||
and thus tty->shutdown() occur via a work queue and simplify all
|
||||
the drivers that use it.
|
||||
*/
|
||||
if (tty_hung_up_p(filp)) {
|
||||
/* serial_hangup already called serial_down at this point.
|
||||
Another user may have already reopened the port but
|
||||
serial_do_free is refcounted */
|
||||
serial_do_free(port);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tty_port_close_start(&port->port, tty, filp) == 0)
|
||||
return;
|
||||
@ -355,7 +371,8 @@ static void serial_hangup(struct tty_struct *tty)
|
||||
struct usb_serial_port *port = tty->driver_data;
|
||||
serial_do_down(port);
|
||||
tty_port_hangup(&port->port);
|
||||
serial_do_free(port);
|
||||
/* We must not free port yet - the USB serial layer depends on it's
|
||||
continued existence */
|
||||
}
|
||||
|
||||
static int serial_write(struct tty_struct *tty, const unsigned char *buf,
|
||||
|
Loading…
Reference in New Issue
Block a user