usb: cdc-wdm: close race between read and workqueue

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: afba937e54 ("USB: CDC WDM driver")
Cc: stable <[email protected]>
Signed-off-by: Oliver Neukum <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
This commit is contained in:
Oliver Neukum authored and Greg Kroah-Hartman committed 2024-03-26 14:56:33 +01:00
1 parent 5d69a3b54e
commit 339f83612f
1 file changed
+5 -1
+5 -1
View File
@@ -485,6 +485,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)
@@ -499,7 +500,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);