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@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=0335df380edd9bd3ff70 Fixes: 60688d5e6e6e ("V4L/DVB (8735): dtv5100: replace dummy frontend by zl10353") Cc: stable@vger.kernel.org Signed-off-by: Nalivayko Sergey Sergey.Nalivayko@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 */
linux-stable-mirror@lists.linaro.org