[lvc-project] [PATCH] dvb-usb: dtv5100: rewrite i2c message usb_control send/recv
Alan Stern
stern at rowland.harvard.edu
Wed Nov 19 18:51:11 MSK 2025
On Mon, Nov 17, 2025 at 06:53:56PM +0300, Nalivayko Sergey wrote:
> 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>
> ---
Can't this problem be fixed more simply by setting the
I2C_AQ_NO_ZERO_LEN_READ adapter quirk flag, as in some of Wolfram Sang's
recent commits?
Alan Stern
> 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