From: "syzbot" <syzbot@kernel.org>
To: syzkaller-upstream-moderation@googlegroups.com
Cc: syzbot@lists.linux.dev
Subject: [PATCH RFC] media: dw2102: Fix null-ptr-deref in i2c transfer callbacks
Date: Mon, 19 Oct 2026 15:10:34 +0000 (UTC) [thread overview]
Message-ID: <9dda9080-8d80-4504-95dd-0faef04af12d@mail.kernel.org> (raw)
When user space issues an I2C_RDWR ioctl on an exposed I2C device
(/dev/i2c-X) with a zero-length message (msg.len == 0), i2cdev_ioctl_rdwr()
allocates the message buffer using memdup_user(..., 0). This causes
kmalloc_track_caller() to return ZERO_SIZE_PTR (0x10). When
su3000_i2c_transfer() subsequently processes the request, commands such as
SU3000_STREAM_CTRL unconditionally dereference msg[j].buf[0] without
verifying that msg[j].len is at least 1. Dereferencing ZERO_SIZE_PTR leads
to a general protection fault and KASAN null-ptr-deref report.
Oops: general protection fault, probably for non-canonical address
0xdffffc0000000002: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000010-0x0000000000000017]
RIP: 0010:su3000_i2c_transfer+0x1aa/0xfc0
drivers/media/usb/dvb-usb/dw2102.c:740
Call Trace:
<TASK>
__i2c_transfer+0x7bf/0x1fe0 drivers/i2c/i2c-core-base.c:-1
i2c_transfer+0x1cb/0x2d0 drivers/i2c/i2c-core-base.c:2350
i2cdev_ioctl_rdwr+0x460/0x740 drivers/i2c/i2c-dev.c:306
i2cdev_ioctl+0x6a5/0x880 drivers/i2c/i2c-dev.c:467
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:597 [inline]
__se_sys_ioctl+0xfc/0x170 fs/ioctl.c:583
do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline]
do_syscall_64+0x155/0x510 arch/x86/entry/syscall_64.c:84
entry_SYSCALL_64_after_hwframe+0x77/0x7f
</TASK>
Although dw2102_i2c_transfer() was previously fixed for this issue in
commit 5ae544d94abc ("media: dw2102: Fix null-ptr-deref in
dw2102_i2c_transfer()"), other transfer callbacks in
drivers/media/usb/dvb-usb/dw2102.c (su3000_i2c_transfer,
dw2102_serit_i2c_transfer, dw2102_earda_i2c_transfer, dw2104_i2c_transfer,
dw3101_i2c_transfer, and s6x0_i2c_transfer) also accessed msg[].buf without
checking msg[].len during operations such as DW2102_RC_QUERY,
DW2102_VOLTAGE_CTRL, DW2102_LED_CTRL, and default write commands.
Additionally, dw2102_earda_i2c_transfer() incorrectly logged msg[1].len
instead of msg[0].len in warning messages for single-message transfers.
Fix these issues by validating msg[].len against the minimum required size
before indexing into or copying to msg[].buf in all dw2102 I2C transfer
callbacks, returning -EOPNOTSUPP on failure, and correct the message index
in dw2102_earda_i2c_transfer() warning logs.
Fixes: d2ffc447cabb ("[media] dw2102: add support for Geniatech SU3000 USB DVB-S2 card")
Assisted-by: Gemini:gemini-4-argon Gemini:gemini-3.8-flash syzbot
Reported-by: syzbot+d99f3a288cc7d8ef60fb@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=d99f3a288cc7d8ef60fb
Link: https://syzkaller.appspot.com/ai_job?id=d863a1b0-1ca0-4436-b7e6-658d0c1cc4be
To: <linux-media@vger.kernel.org>
To: "Mauro Carvalho Chehab" <mchehab@kernel.org>
To: "Igor M. Liplianin" <liplianin@me.by>
Cc: <linux-kernel@vger.kernel.org>
---
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c
index 4fecf2f96..a76bc2887 100644
--- a/drivers/media/usb/dvb-usb/dw2102.c
+++ b/drivers/media/usb/dvb-usb/dw2102.c
@@ -265,12 +265,20 @@ static int dw2102_serit_i2c_transfer(struct i2c_adapter *adap,
msg[0].len + 2, DW210X_WRITE_MSG);
break;
case(DW2102_RC_QUERY):
+ if (msg[0].len < 2) {
+ num = -EOPNOTSUPP;
+ break;
+ }
dw210x_op_rw(d->udev, 0xb8, 0, 0,
buf6, 2, DW210X_READ_MSG);
msg[0].buf[0] = buf6[0];
msg[0].buf[1] = buf6[1];
break;
case(DW2102_VOLTAGE_CTRL):
+ if (msg[0].len < 1) {
+ num = -EOPNOTSUPP;
+ break;
+ }
buf6[0] = 0x30;
buf6[1] = msg[0].buf[0];
dw210x_op_rw(d->udev, 0xb2, 0, 0,
@@ -334,7 +342,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
if (2 + msg[0].len > sizeof(obuf)) {
warn("i2c wr: len=%d is too big!\n",
- msg[1].len);
+ msg[0].len);
ret = -EOPNOTSUPP;
goto unlock;
}
@@ -352,7 +360,7 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
if (2 + msg[0].len > sizeof(obuf)) {
warn("i2c wr: len=%d is too big!\n",
- msg[1].len);
+ msg[0].len);
ret = -EOPNOTSUPP;
goto unlock;
}
@@ -367,6 +375,10 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
case(DW2102_RC_QUERY): {
u8 ibuf[2];
+ if (msg[0].len < 2) {
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
dw210x_op_rw(d->udev, 0xb8, 0, 0,
ibuf, 2, DW210X_READ_MSG);
memcpy(msg[0].buf, ibuf, 2);
@@ -375,6 +387,10 @@ static int dw2102_earda_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg ms
case(DW2102_VOLTAGE_CTRL): {
u8 obuf[2];
+ if (msg[0].len < 1) {
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
obuf[0] = 0x30;
obuf[1] = msg[0].buf[0];
dw210x_op_rw(d->udev, 0xb2, 0, 0,
@@ -407,6 +423,10 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
case(DW2102_RC_QUERY): {
u8 ibuf[2];
+ if (msg[j].len < 2) {
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
dw210x_op_rw(d->udev, 0xb8, 0, 0,
ibuf, 2, DW210X_READ_MSG);
memcpy(msg[j].buf, ibuf, 2);
@@ -415,6 +435,10 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
case(DW2102_VOLTAGE_CTRL): {
u8 obuf[2];
+ if (msg[j].len < 1) {
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
obuf[0] = 0x30;
obuf[1] = msg[j].buf[0];
dw210x_op_rw(d->udev, 0xb2, 0, 0,
@@ -444,6 +468,9 @@ static int dw2104_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], i
DW210X_READ_MSG);
memcpy(msg[j].buf, ibuf + 2, msg[j].len);
mdelay(10);
+ } else if (msg[j].len < 1) {
+ ret = -EOPNOTSUPP;
+ goto unlock;
} else if (((msg[j].buf[0] == 0xb0) && (msg[j].addr == 0x68)) ||
((msg[j].buf[0] == 0xf7) && (msg[j].addr == 0x55))) {
/* write firmware */
@@ -557,6 +584,10 @@ static int dw3101_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
case(DW2102_RC_QUERY): {
u8 ibuf[2];
+ if (msg[0].len < 2) {
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
dw210x_op_rw(d->udev, 0xb8, 0, 0,
ibuf, 2, DW210X_READ_MSG);
memcpy(msg[0].buf, ibuf, 2);
@@ -597,6 +628,10 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
case (DW2102_RC_QUERY): {
u8 ibuf[5];
+ if (msg[j].len < 2) {
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
dw210x_op_rw(d->udev, 0xb8, 0, 0,
ibuf, 5, DW210X_READ_MSG);
memcpy(msg[j].buf, ibuf + 3, 2);
@@ -605,6 +640,10 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
case (DW2102_VOLTAGE_CTRL): {
u8 obuf[2];
+ if (msg[j].len < 2) {
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
obuf[0] = 1;
obuf[1] = msg[j].buf[1];/* off-on */
dw210x_op_rw(d->udev, 0x8a, 0, 0,
@@ -618,6 +657,10 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
case (DW2102_LED_CTRL): {
u8 obuf[2];
+ if (msg[j].len < 1) {
+ ret = -EOPNOTSUPP;
+ goto unlock;
+ }
obuf[0] = 5;
obuf[1] = msg[j].buf[0];
dw210x_op_rw(d->udev, 0x8a, 0, 0,
@@ -647,6 +690,9 @@ static int s6x0_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
DW210X_READ_MSG);
memcpy(msg[j].buf, ibuf, msg[j].len);
break;
+ } else if (msg[j].len < 1) {
+ ret = -EOPNOTSUPP;
+ goto unlock;
} else if ((msg[j].buf[0] == 0xb0) && (msg[j].addr == 0x68)) {
/* write firmware */
u8 obuf[19];
@@ -737,6 +783,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 +795,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)
base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
--
This is an AI-generated patch subject to moderation.
Reply with '#syz upstream' to Sign-off the patch as a human author
and send it to the upstream kernel mailing lists.
Reply with '#syz reject' to reject it ('#syz unreject' to undo).
See https://goo.gle/syzbot-ai-patches for information about AI-generated patches.
You can comment on the patch as usual, syzbot will try to address
the comments and send a new version of the patch if necessary.
syzbot engineers can be reached at syzkaller@googlegroups.com.
reply other threads:[~2026-10-19 15:10 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9dda9080-8d80-4504-95dd-0faef04af12d@mail.kernel.org \
--to=syzbot@kernel.org \
--cc=syzbot@lists.linux.dev \
--cc=syzkaller-upstream-moderation@googlegroups.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.