Commit 80c4bbb2 authored by Michael Zaidman's avatar Michael Zaidman Committed by Jiri Kosina
Browse files

HID: ft260: validate i2c input report length



Add two checks to ft260_raw_event() to prevent out-of-bounds reads
from malicious or malfunctioning devices:

First, reject reports shorter than the 2-byte header (report ID +
length fields). Without this, even accessing xfer->length on a
1-byte report is an OOB read.

Second, validate xfer->length against the actual data capacity of
the received HID report. Each I2C data report ID (0xD0 through
0xDE) defines a different report size in the HID descriptor, so the
available payload varies per report. A corrupted length field could
cause memcpy to read beyond the report buffer.

Reported-by: default avatarSebastián Josué Alba Vives <sebasjosue84@gmail.com>
Signed-off-by: default avatarMichael Zaidman <michael.zaidman@gmail.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.com>
parent 278dd048
Loading
Loading
Loading
Loading
+14 −2
Original line number Diff line number Diff line
@@ -1068,10 +1068,22 @@ static int ft260_raw_event(struct hid_device *hdev, struct hid_report *report,
	struct ft260_device *dev = hid_get_drvdata(hdev);
	struct ft260_i2c_input_report *xfer = (void *)data;

	if (size < offsetof(struct ft260_i2c_input_report, data)) {
		hid_err(hdev, "short report %d\n", size);
		return -1;
	}

	if (xfer->report >= FT260_I2C_REPORT_MIN &&
	    xfer->report <= FT260_I2C_REPORT_MAX) {
		ft260_dbg("i2c resp: rep %#02x len %d\n", xfer->report,
			  xfer->length);
		ft260_dbg("i2c resp: rep %#02x len %d size %d\n",
			  xfer->report, xfer->length, size);

		if (xfer->length > size -
		    offsetof(struct ft260_i2c_input_report, data)) {
			hid_err(hdev, "report %#02x: length %d exceeds HID report size\n",
				xfer->report, xfer->length);
			return -1;
		}

		if ((dev->read_buf == NULL) ||
		    (xfer->length > dev->read_len - dev->read_idx)) {