[PATCH] i2c: cp2615: Validate read length before copying
Triet Hoang <[email protected]>
| Newsgroups | org.kernel.vger.linux-i2c,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
The read_len field comes from the untrusted USB payload, which could potentially exceed the client's originally requested buffer length or MAX_I2C_SIZE, allowing an out-of-bounds read and write. Limit read_len to the maximum size of the response buffer and return -EPROTO for an invalid response. Signed-off-by: Triet Hoang <[email protected]> --- drivers/i2c/busses/i2c-cp2615.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-cp2615.c b/drivers/i2c/busses/i2c-cp2615.c index 951de6249834..2c79530da306 100644 --- a/drivers/i2c/busses/i2c-cp2615.c +++ b/drivers/i2c/busses/i2c-cp2615.c @@ -136,7 +136,7 @@ cp2615_i2c_send(struct usb_interface *usbif, struct cp2615_i2c_transfer *i2c_w) } static int -cp2615_i2c_recv(struct usb_interface *usbif, unsigned char tag, void *buf) +cp2615_i2c_recv(struct usb_interface *usbif, unsigned char tag, void *buf, int len) { struct usb_device *usbdev = interface_to_usbdev(usbif); struct cp2615_iop_msg *msg; @@ -160,6 +160,11 @@ cp2615_i2c_recv(struct usb_interface *usbif, unsigned char tag, void *buf) return -EIO; } + if (i2c_r->read_len > len || i2c_r->read_len > MAX_I2C_SIZE) { + kfree(msg); + return -EPROTO; + } + res = cp2615_check_status(i2c_r->status); if (!res) memcpy(buf, &i2c_r->data, i2c_r->read_len); @@ -236,7 +241,7 @@ cp2615_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ret = cp2615_i2c_send(usbif, &i2c_w); if (ret) break; - ret = cp2615_i2c_recv(usbif, i2c_w.tag, msg->buf); + ret = cp2615_i2c_recv(usbif, i2c_w.tag, msg->buf, msg->len); } if (ret < 0) return ret; -- 2.53.0