[lvc-project] [PATCH v2] dvb-usb: dtv5100: rewrite i2c message usb_control send/recv

Nalivayko Sergey Sergey.Nalivayko at kaspersky.com
Fri Nov 21 16:23:31 MSK 2025


syzbot reports a WARNING issue as below:

usb 1-1: BOGUS control dir, pipe 80000280 doesn't match bRequestType c0
WARNING: CPU: 0 PID: 5833 at drivers/usb/core/urb.c:413 usb_submit_urb+0x1112/0x1870 drivers/usb/core/urb.c:411
Modules linked in:
CPU: 0 UID: 0 PID: 5833 Comm: syz-executor411 Not tainted 6.15.0-syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/07/2025
Call Trace:
 <TASK>
 usb_start_wait_urb+0x114/0x4c0 drivers/usb/core/message.c:59
 usb_internal_control_msg drivers/usb/core/message.c:103 [inline]
 usb_control_msg+0x232/0x3e0 drivers/usb/core/message.c:154
 dtv5100_i2c_msg+0x250/0x330 drivers/media/usb/dvb-usb/dtv5100.c:60
 dtv5100_i2c_xfer+0x1a4/0x3c0 drivers/media/usb/dvb-usb/dtv5100.c:86
 __i2c_transfer+0x871/0x2170 drivers/i2c/i2c-core-base.c:-1
 i2c_transfer+0x25b/0x3a0 drivers/i2c/i2c-core-base.c:2315
 i2c_transfer_buffer_flags+0x105/0x190 drivers/i2c/i2c-core-base.c:2343
 i2c_master_send include/linux/i2c.h:109 [inline]
 i2cdev_write+0x112/0x1b0 drivers/i2c/i2c-dev.c:183
 do_loop_readv_writev include/linux/uio.h:-1 [inline]
 vfs_writev+0x4a5/0x9a0 fs/read_write.c:1057
 do_writev+0x14d/0x2d0 fs/read_write.c:1101
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xf6/0x210 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
 </TASK>

The issue occurs due to insufficient validation of data passed to the USB API.
In the current implementation, the dtv5100 driver expects two I2C non-zero 
length messages for a combined write/read request. However, when 
only a single message is provided, the driver incorrectly processes message
of size 1, passing a read data size of zero to the dtv5100_i2c_msg function.

When usb_control_msg() is called with a PIPEOUT type and a read length of
zero, a mismatch error occurs between the operation type and the expected
transfer direction in function usb_submit_urb. This is the trigger
for warning.

Replace usb_control_msg() with usb_control_msg_recv() and
usb_control_msg_send() to rely on the USB API for proper validation and
prevent inconsistencies in the future.

Reported-by: syzbot+0335df380edd9bd3ff70 at syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=0335df380edd9bd3ff70
Fixes: 60688d5e6e6e ("V4L/DVB (8735): dtv5100: replace dummy frontend by zl10353")
Cc: stable at vger.kernel.org
Signed-off-by: Nalivayko Sergey <Sergey.Nalivayko at kaspersky.com>
---
v2: Expand problem description.

 drivers/media/usb/dvb-usb/dtv5100.c | 21 +++++++++------------
 1 file changed, 9 insertions(+), 12 deletions(-)

diff --git a/drivers/media/usb/dvb-usb/dtv5100.c b/drivers/media/usb/dvb-usb/dtv5100.c
index 3d85c6f7f6ec..05860f5d5053 100644
--- a/drivers/media/usb/dvb-usb/dtv5100.c
+++ b/drivers/media/usb/dvb-usb/dtv5100.c
@@ -26,40 +26,37 @@ static int dtv5100_i2c_msg(struct dvb_usb_device *d, u8 addr,
 			   u8 *wbuf, u16 wlen, u8 *rbuf, u16 rlen)
 {
 	struct dtv5100_state *st = d->priv;
-	unsigned int pipe;
 	u8 request;
 	u8 type;
 	u16 value;
 	u16 index;
 
+	index = (addr << 8) + wbuf[0];
+
+	memcpy(st->data, rbuf, rlen);
+	msleep(1); /* avoid I2C errors */
+
 	switch (wlen) {
 	case 1:
 		/* write { reg }, read { value } */
-		pipe = usb_rcvctrlpipe(d->udev, 0);
 		request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_READ :
 							DTV5100_TUNER_READ);
 		type = USB_TYPE_VENDOR | USB_DIR_IN;
 		value = 0;
-		break;
+		return usb_control_msg_recv(d->udev, 0, request, type, value, index,
+			st->data, rlen, DTV5100_USB_TIMEOUT, GFP_KERNEL);
 	case 2:
 		/* write { reg, value } */
-		pipe = usb_sndctrlpipe(d->udev, 0);
 		request = (addr == DTV5100_DEMOD_ADDR ? DTV5100_DEMOD_WRITE :
 							DTV5100_TUNER_WRITE);
 		type = USB_TYPE_VENDOR | USB_DIR_OUT;
 		value = wbuf[1];
-		break;
+		return usb_control_msg_send(d->udev, 0, request, type, value, index,
+			st->data, rlen, DTV5100_USB_TIMEOUT, GFP_KERNEL);
 	default:
 		warn("wlen = %x, aborting.", wlen);
 		return -EINVAL;
 	}
-	index = (addr << 8) + wbuf[0];
-
-	memcpy(st->data, rbuf, rlen);
-	msleep(1); /* avoid I2C errors */
-	return usb_control_msg(d->udev, pipe, request,
-			       type, value, index, st->data, rlen,
-			       DTV5100_USB_TIMEOUT);
 }
 
 /* I2C */
-- 
2.39.5



More information about the lvc-project mailing list