[PATCH] media: dw2102: Fix null-ptr-deref in su3000_i2c_transfer()
From: Denis Arefev
Date: Fri Feb 27 2026 - 07:41:39 EST
general protection fault, probably for non-canonical address
KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017]
...
Call Trace:
<TASK>
__i2c_transfer+0x868/0x2080 drivers/i2c/i2c-core-base.c:-1
i2c_transfer+0x250/0x390 drivers/i2c/i2c-core-base.c:2328
i2cdev_ioctl_rdwr+0x3b0/0x690 drivers/i2c/i2c-dev.c:297
i2cdev_ioctl+0x646/0x7e0 drivers/i2c/i2c-dev.c:458
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:871 [inline]
__se_sys_ioctl+0xfd/0x170 fs/ioctl.c:857
do_syscall_x64 arch/x86/entry/common.c:51 [inline]
do_syscall_64+0x55/0xb0 arch/x86/entry/common.c:81
entry_SYSCALL_64_after_hwframe+0x68/0xd2
RIP: 0033:0x7f1bc3f8ebe9
The user transmits messages of invalid length via ioctl, some of which may
be zero length. This causes the i2cdev_ioctl_rdwr() function to allocate
zero-length memory for msgs[i].buf when executing memdup_user(), resulting
in a ZERO_SIZE_PTR error. The i2cdev_ioctl_rdwr() function does not handle
this situation for this adapter, resulting in a null-ptr-deref error when
accessing msgs[i].buf in su3000_i2c_transfer().
Adding the necessary checks to su3000_i2c_transfer() resolves the
ZERO_SIZE_PTR error.
Fixes: d2ffc447cabb ("[media] dw2102: add support for Geniatech SU3000 USB DVB-S2 card")
Reported-by: syzbot+d99f3a288cc7d8ef60fb@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://syzkaller.appspot.com/bug?extid=d99f3a288cc7d8ef60fb
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Denis Arefev <arefev@xxxxxxxxx>
---
drivers/media/usb/dvb-usb/dw2102.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
index 4fecf2f965e9..ad9c0374b4cb 100644
--- a/drivers/media/usb/dvb-usb/dw2102.c
+++ b/drivers/media/usb/dvb-usb/dw2102.c
@@ -737,6 +737,10 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
while (j < num) {
switch (msg[j].addr) {
case SU3000_STREAM_CTRL:
+ if (msg[j].len < 1) {
+ num = -EOPNOTSUPP;
+ break;
+ }
state->data[0] = msg[j].buf[0] + 0x36;
state->data[1] = 3;
state->data[2] = 0;
@@ -745,6 +749,10 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
err("i2c transfer failed.");
break;
case DW2102_RC_QUERY:
+ if (msg[j].len < 2) {
+ num = -EOPNOTSUPP;
+ break;
+ }
state->data[0] = 0x10;
if (dvb_usb_generic_rw(d, state->data, 1,
state->data, 2, 0) < 0)
--
2.43.0