[PATCH v2 1/4] USB: serial: fix port tear down use-after-free
Johan Hovold <[email protected]>
| Newsgroups | org.kernel.vger.stable,org.kernel.vger.linux-kernel,org.kernel.vger.linux-usb |
|---|---|
| Message-ID | <[email protected]> |
Some drivers for multiport devices access port driver data from
completion handlers of shared URBs submitted at attach() or first open()
and stopped at disconnect() or last close(), respectively.
A simple NULL check before accessing the driver data makes sure that a
port state container has at least been allocated, but a completion
handler can still race with port tear down.
Reorder the disconnect handling so that ports are not deregistered (and
their driver data freed) until after all ports have been hung up and the
driver disconnect() callback has run so that all I/O has been stopped.
Fixes: 2d93148ab698 ("USB: serial: fix lifetime and locking problems")
Reported-by: [email protected]
Link: https://lore.kernel.org/all/[email protected]/
Cc: [email protected] # 2.6.30
Cc: Alan Stern <[email protected]>
Reviewed-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: Johan Hovold <[email protected]>
---
drivers/usb/serial/usb-serial.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 17edc057a311..a4fbc849c0fa 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -1191,12 +1191,17 @@ static void usb_serial_disconnect(struct usb_interface *interface)
usb_serial_port_poison_urbs(port);
wake_up_interruptible(&port->port.delta_msr_wait);
cancel_work_sync(&port->work);
- if (device_is_registered(&port->dev))
- device_del(&port->dev);
}
+
if (serial->type->disconnect)
serial->type->disconnect(serial);
+ for (i = 0; i < serial->num_ports; ++i) {
+ port = serial->port[i];
+ if (device_is_registered(&port->dev))
+ device_del(&port->dev);
+ }
+
release_sibling(serial, interface);
/* let the last holder of this object cause it to be cleaned up */
--
2.54.0