diff options
author | Johan Hovold <johan@kernel.org> | 2019-10-11 11:57:35 +0200 |
---|---|---|
committer | Johan Hovold <johan@kernel.org> | 2019-10-16 10:29:11 +0200 |
commit | 6f1d1dc8d540a9aa6e39b9cb86d3a67bbc1c8d8d (patch) | |
tree | e8b49edb45f79e4214f2555d8329604d5e921662 /drivers | |
parent | Linux 5.4-rc3 (diff) | |
download | linux-6f1d1dc8d540a9aa6e39b9cb86d3a67bbc1c8d8d.tar.xz linux-6f1d1dc8d540a9aa6e39b9cb86d3a67bbc1c8d8d.zip |
USB: serial: ti_usb_3410_5052: fix port-close races
Fix races between closing a port and opening or closing another port on
the same device which could lead to a failure to start or stop the
shared interrupt URB. The latter could potentially cause a
use-after-free or worse in the completion handler on driver unbind.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/usb/serial/ti_usb_3410_5052.c | 10 |
1 files changed, 3 insertions, 7 deletions
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index dd0ad67aa71e..9174ba2e06da 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -776,7 +776,6 @@ static void ti_close(struct usb_serial_port *port) struct ti_port *tport; int port_number; int status; - int do_unlock; unsigned long flags; tdev = usb_get_serial_data(port->serial); @@ -800,16 +799,13 @@ static void ti_close(struct usb_serial_port *port) "%s - cannot send close port command, %d\n" , __func__, status); - /* if mutex_lock is interrupted, continue anyway */ - do_unlock = !mutex_lock_interruptible(&tdev->td_open_close_lock); + mutex_lock(&tdev->td_open_close_lock); --tport->tp_tdev->td_open_port_count; - if (tport->tp_tdev->td_open_port_count <= 0) { + if (tport->tp_tdev->td_open_port_count == 0) { /* last port is closed, shut down interrupt urb */ usb_kill_urb(port->serial->port[0]->interrupt_in_urb); - tport->tp_tdev->td_open_port_count = 0; } - if (do_unlock) - mutex_unlock(&tdev->td_open_close_lock); + mutex_unlock(&tdev->td_open_close_lock); } |