Skip to content

Commit

Permalink
tty: Fix close races in USB serial
Browse files Browse the repository at this point in the history
USB serial has always had races where the tty port usage count can hit zero
during a receive event. The internal locking is a mutex so we can't use
that in the IRQ handlers.

With krefs we can tackle this differently but we still need to be careful.

Signed-off-by: Alan Cox <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Alan Cox authored and torvalds committed Jan 2, 2009
1 parent 7e94b1d commit 4bd43f2
Showing 1 changed file with 10 additions and 5 deletions.
15 changes: 10 additions & 5 deletions drivers/usb/serial/usb-serial.c
Original file line number Diff line number Diff line change
Expand Up @@ -269,29 +269,34 @@ static void serial_close(struct tty_struct *tty, struct file *filp)
return;
}

--port->port.count;
if (port->port.count == 0)
if (port->port.count == 1)
/* only call the device specific close if this
* port is being closed by the last owner */
* port is being closed by the last owner. Ensure we do
* this before we drop the port count. The call is protected
* by the port mutex
*/
port->serial->type->close(tty, port, filp);

if (port->port.count == (port->console? 1 : 0)) {
if (port->port.count == (port->console ? 2 : 1)) {
struct tty_struct *tty = tty_port_tty_get(&port->port);
if (tty) {
/* We must do this before we drop the port count to
zero. */
if (tty->driver_data)
tty->driver_data = NULL;
tty_port_tty_set(&port->port, NULL);
tty_kref_put(tty);
}
}

if (port->port.count == 0) {
if (port->port.count == 1) {
mutex_lock(&port->serial->disc_mutex);
if (!port->serial->disconnected)
usb_autopm_put_interface(port->serial->interface);
mutex_unlock(&port->serial->disc_mutex);
module_put(port->serial->type->driver.owner);
}
--port->port.count;

mutex_unlock(&port->mutex);
usb_serial_put(port->serial);
Expand Down

0 comments on commit 4bd43f2

Please sign in to comment.