]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
HID: ft260: validate i2c input report length
authorMichael Zaidman <michael.zaidman@gmail.com>
Sat, 11 Apr 2026 06:24:37 +0000 (09:24 +0300)
committerJiri Kosina <jkosina@suse.com>
Tue, 28 Apr 2026 16:24:52 +0000 (18:24 +0200)
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: SebastiƔn JosuƩ Alba Vives <sebasjosue84@gmail.com>
Signed-off-by: Michael Zaidman <michael.zaidman@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
drivers/hid/hid-ft260.c

index 333341e80b0ec6a35f66d7f0359b58b9b42c0ec5..70e2eedb465af1eee79c15c28c972de19c9e736d 100644 (file)
@@ -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)) {