On Fri Aug 14 21:41:00 2026 +0800, Ruoyu Wang wrote:
> start_urb_transfer() stores each allocated URB in dev->urbs[], but sets
> urb_streaming only after all URBs have been submitted. If a later URB or
> transfer buffer allocation fails, earlier entries are left allocated. A
> submission failure calls stop_urb_transfer(), but that function returns
> immediately while urb_streaming is false, leaving both submitted and
> unsubmitted URBs behind.
>
> Make stop_urb_transfer() release every populated slot regardless of the
> streaming flag and clear each slot after release. Route all start errors
> through this cleanup. usb_kill_urb() safely handles both submitted and
> unsubmitted URBs, while the existing preallocation check preserves the
> lifetime of shared transfer buffers.
>
> This issue was found by a static analysis checker and confirmed by
> manual source review.
>
> Fixes: 265a6510629a ("V4L/DVB (7621): Add support for Hauppauge
> HVR950Q/HVR850/FusioHDTV7-USB")
> Cc: [email protected]
> Signed-off-by: Ruoyu Wang <[email protected]>
> Signed-off-by: Hans Verkuil <[email protected]>
Patch committed.
Thanks,
Hans Verkuil
drivers/media/usb/au0828/au0828-dvb.c | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
---
diff --git a/drivers/media/usb/au0828/au0828-dvb.c
b/drivers/media/usb/au0828/au0828-dvb.c
index d3fff47f0edf..601a12e122f1 100644
--- a/drivers/media/usb/au0828/au0828-dvb.c
+++ b/drivers/media/usb/au0828/au0828-dvb.c
@@ -163,9 +163,6 @@ static int stop_urb_transfer(struct au0828_dev *dev)
dprintk(2, "%s()\n", __func__);
- if (!dev->urb_streaming)
- return 0;
-
if (dev->bulk_timeout_running == 1) {
dev->bulk_timeout_running = 0;
timer_delete(&dev->bulk_timeout);
@@ -179,6 +176,7 @@ static int stop_urb_transfer(struct au0828_dev *dev)
kfree(dev->urbs[i]->transfer_buffer);
usb_free_urb(dev->urbs[i]);
+ dev->urbs[i] = NULL;
}
}
@@ -200,8 +198,10 @@ static int start_urb_transfer(struct au0828_dev *dev)
for (i = 0; i < URB_COUNT; i++) {
dev->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
- if (!dev->urbs[i])
- return -ENOMEM;
+ if (!dev->urbs[i]) {
+ ret = -ENOMEM;
+ goto err;
+ }
purb = dev->urbs[i];
@@ -217,7 +217,7 @@ static int start_urb_transfer(struct au0828_dev *dev)
ret = -ENOMEM;
pr_err("%s: failed big buffer allocation, err = %d\n",
__func__, ret);
- return ret;
+ goto err;
}
purb->status = -EINPROGRESS;
@@ -235,10 +235,9 @@ static int start_urb_transfer(struct au0828_dev *dev)
for (i = 0; i < URB_COUNT; i++) {
ret = usb_submit_urb(dev->urbs[i], GFP_ATOMIC);
if (ret != 0) {
- stop_urb_transfer(dev);
pr_err("%s: failed urb submission, err = %d\n",
__func__, ret);
- return ret;
+ goto err;
}
}
@@ -249,6 +248,10 @@ static int start_urb_transfer(struct au0828_dev *dev)
dev->bulk_timeout_running = 1;
return 0;
+
+err:
+ stop_urb_transfer(dev);
+ return ret;
}
static void au0828_start_transport(struct au0828_dev *dev)
_______________________________________________
linuxtv-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]