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

Nalivayko Sergey Sergey.Nalivayko at kaspersky.com
Mon Nov 17 18:53:56 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 case where the operation type is read
but the read length is zero is not handled properly, which makes no sense.

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>
---
 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