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 <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>
This commit is contained in:
parent
5d69a3b54e
commit
339f83612f
1 changed files with 5 additions and 1 deletions
|
@ -485,6 +485,7 @@ out_free_mem:
|
||||||
static int service_outstanding_interrupt(struct wdm_device *desc)
|
static int service_outstanding_interrupt(struct wdm_device *desc)
|
||||||
{
|
{
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
int used;
|
||||||
|
|
||||||
/* submit read urb only if the device is waiting for it */
|
/* submit read urb only if the device is waiting for it */
|
||||||
if (!desc->resp_count || !--desc->resp_count)
|
if (!desc->resp_count || !--desc->resp_count)
|
||||||
|
@ -499,7 +500,10 @@ static int service_outstanding_interrupt(struct wdm_device *desc)
|
||||||
goto out;
|
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);
|
spin_unlock_irq(&desc->iuspin);
|
||||||
rv = usb_submit_urb(desc->response, GFP_KERNEL);
|
rv = usb_submit_urb(desc->response, GFP_KERNEL);
|
||||||
spin_lock_irq(&desc->iuspin);
|
spin_lock_irq(&desc->iuspin);
|
||||||
|
|
Loading…
Add table
Reference in a new issue