[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