aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOliver Neukum <oneukum@suse.com>2024-03-14 12:50:48 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-04-13 12:59:05 +0200
commit9b319f4a88094b2e020e6db6e819c808d890098d (patch)
tree7138a3542bf140d3dbbe993c04b7b7ffe1333f18
parent6d9395ba7f85bdb7af0b93272e537484ecbeff48 (diff)
downloadchromeos-9b319f4a88094b2e020e6db6e819c808d890098d.tar.gz
usb: cdc-wdm: close race between read and workqueue
commit 339f83612f3a569b194680768b22bf113c26a29d upstream. wdm_read() cannot race with itself. However, in service_outstanding_interrupt() it can race with the workqueue, which can be triggered by error handling. Hence we need to make sure that the WDM_RESPONDING flag is not just only set but tested. Fixes: afba937e540c9 ("USB: CDC WDM driver") Cc: stable <stable@kernel.org> Signed-off-by: Oliver Neukum <oneukum@suse.com> Link: https://lore.kernel.org/r/20240314115132.3907-1-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/class/cdc-wdm.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c
index 80332b6a1963e6..58423b16022b49 100644
--- a/drivers/usb/class/cdc-wdm.c
+++ b/drivers/usb/class/cdc-wdm.c
@@ -471,6 +471,7 @@ out_free_mem:
static int service_outstanding_interrupt(struct wdm_device *desc)
{
int rv = 0;
+ int used;
/* submit read urb only if the device is waiting for it */
if (!desc->resp_count || !--desc->resp_count)
@@ -485,7 +486,10 @@ static int service_outstanding_interrupt(struct wdm_device *desc)
goto out;
}
- set_bit(WDM_RESPONDING, &desc->flags);
+ used = test_and_set_bit(WDM_RESPONDING, &desc->flags);
+ if (used)
+ goto out;
+
spin_unlock_irq(&desc->iuspin);
rv = usb_submit_urb(desc->response, GFP_KERNEL);
spin_lock_irq(&desc->iuspin);