[PATCH] media: dvb-usb: opera1: reject failed control transfers

From: Yousef Alhouseen

Date: Tue Jun 30 2026 - 06:50:55 EST


opera1_xilinx_rw() copies its temporary buffer to callers even when
the USB control transfer fails or returns short. Read callers can
then consume uninitialized heap data, including the firmware-loader
status byte.

Return immediately on transfer errors and translate short transfers
to -EIO before exposing the buffer.

Signed-off-by: Yousef Alhouseen <alhouseenyousef@xxxxxxxxx>
---
drivers/media/usb/dvb-usb/opera1.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/media/usb/dvb-usb/opera1.c b/drivers/media/usb/dvb-usb/opera1.c
index 3c79cc6848b4..e5172dcf782e 100644
--- a/drivers/media/usb/dvb-usb/opera1.c
+++ b/drivers/media/usb/dvb-usb/opera1.c
@@ -61,6 +61,12 @@ static int opera1_xilinx_rw(struct usb_device *dev, u8 request, u16 value,
ret = usb_control_msg(dev, pipe, request,
request_type | USB_TYPE_VENDOR, value, 0x0,
buf, len, 2000);
+ if (ret < 0)
+ goto out;
+ if (ret != len) {
+ ret = -EIO;
+ goto out;
+ }

if (request == OPERA_TUNER_REQ) {
tmp = buf[0];
@@ -460,8 +466,20 @@ static int opera1_xilinx_load_firmware(struct usb_device *dev,
return ret;
} else {
p = kmalloc(fw->size, GFP_KERNEL);
- opera1_xilinx_rw(dev, 0xbc, 0x00, &testval, 1, OPERA_READ_MSG);
- if (p != NULL && testval != 0x67) {
+ if (!p) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = opera1_xilinx_rw(dev, 0xbc, 0x00, &testval, 1,
+ OPERA_READ_MSG);
+ if (ret != 1) {
+ if (ret >= 0)
+ ret = -EIO;
+ goto out;
+ }
+
+ if (testval != 0x67) {

u8 reset = 0, fpga_command = 0;
memcpy(p, fw->data, fw->size);
@@ -492,6 +510,7 @@ static int opera1_xilinx_load_firmware(struct usb_device *dev,
}
}
}
+out:
kfree(p);
release_firmware(fw);
return ret;
--
2.54.0