diff options
author | Johan Hovold <johan@kernel.org> | 2020-10-26 09:25:48 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-11-10 10:22:20 +0100 |
commit | d722e7ed6446347a76f65d83620cfa545546e204 (patch) | |
tree | 9f8b0a2d1425b5cd4066fd9787f6a3ebecc790ca | |
parent | a8675c12b1cf04fa1f6d83a98401856f87c436ce (diff) | |
download | linux-stable-d722e7ed6446347a76f65d83620cfa545546e204.tar.gz linux-stable-d722e7ed6446347a76f65d83620cfa545546e204.tar.bz2 linux-stable-d722e7ed6446347a76f65d83620cfa545546e204.zip |
USB: serial: cyberjack: fix write-URB completion race
commit 985616f0457d9f555fff417d0da56174f70cc14f upstream.
The write-URB busy flag was being cleared before the completion handler
was done with the URB, something which could lead to corrupt transfers
due to a racing write request if the URB is resubmitted.
Fixes: 507ca9bc0476 ("[PATCH] USB: add ability for usb-serial drivers to determine if their write urb is currently being used.")
Cc: stable <stable@vger.kernel.org> # 2.6.13
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/serial/cyberjack.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 8948f375e75d..5a29ea0d00c5 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -368,11 +368,12 @@ static void cyberjack_write_bulk_callback(struct urb *urb) struct cyberjack_private *priv = usb_get_serial_port_data(port); struct device *dev = &port->dev; int status = urb->status; + bool resubmitted = false; - set_bit(0, &port->write_urbs_free); if (status) { dev_dbg(dev, "%s - nonzero write bulk status received: %d\n", __func__, status); + set_bit(0, &port->write_urbs_free); return; } @@ -405,6 +406,8 @@ static void cyberjack_write_bulk_callback(struct urb *urb) goto exit; } + resubmitted = true; + dev_dbg(dev, "%s - priv->wrsent=%d\n", __func__, priv->wrsent); dev_dbg(dev, "%s - priv->wrfilled=%d\n", __func__, priv->wrfilled); @@ -421,6 +424,8 @@ static void cyberjack_write_bulk_callback(struct urb *urb) exit: spin_unlock(&priv->lock); + if (!resubmitted) + set_bit(0, &port->write_urbs_free); usb_serial_port_softint(port); } |