syzbot reports a general protection fault caused by su3000_i2c_transfer() dereferencing msg->buf without validating the message length or buffer pointer. Although i2c-dev blocks zero-length messages, malformed I²C messages can still reach the driver through the DVB USB subsystem.
Add strict validation of each message to prevent NULL-pointer dereferences.
Reported-by: syzbot+d99f3a288cc7d8ef60fb@syzkaller.appspotmail.com Fixes: 0e148a522b84 ("media: dw2102: Don't translate i2c read into write") Closes: https://syzkaller.appspot.com/bug?extid=d99f3a288cc7d8ef60fb Cc: stable@vger.kernel.org Signed-off-by: Dharanitharan R dharanitharan725@gmail.com --- drivers/media/usb/dvb-usb/dw2102.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
diff --git a/drivers/media/usb/dvb-usb/dw2102.c b/drivers/media/usb/dvb-usb/dw2102.c index 4fecf2f965e9..0dd210ea16f3 100644 --- a/drivers/media/usb/dvb-usb/dw2102.c +++ b/drivers/media/usb/dvb-usb/dw2102.c @@ -733,6 +733,36 @@ static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[], return -EAGAIN; }
+ /* Validate incoming I²C messages */ + if (!msg || num <= 0) { + mutex_unlock(&d->data_mutex); + mutex_unlock(&d->i2c_mutex); + return -EINVAL; + } + + for (j = 0; j < num; j++) { + /* msg buffer must exist */ + if (!msg[j].buf) { + mutex_unlock(&d->data_mutex); + mutex_unlock(&d->i2c_mutex); + return -EINVAL; + } + + /* zero or negative length is invalid */ + if (msg[j].len <= 0) { + mutex_unlock(&d->data_mutex); + mutex_unlock(&d->i2c_mutex); + return -EINVAL; + } + + /* protect against unreasonable sizes */ + if (msg[j].len > 256) { + mutex_unlock(&d->data_mutex); + mutex_unlock(&d->i2c_mutex); + return -EOPNOTSUPP; + } + } + j = 0; while (j < num) { switch (msg[j].addr) {