[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