]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
Input: iforce - validate input packet lengths
authorPengpeng Hou <pengpeng@iscas.ac.cn>
Sat, 25 Jul 2026 03:46:27 +0000 (20:46 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Sat, 25 Jul 2026 03:49:53 +0000 (20:49 -0700)
iforce_process_packet() reads fixed fields from joystick, wheel and
status packets without first checking their lengths. In particular, the
shared hats-and-buttons helper unconditionally reads data[6]. The status
tail is a sequence of 16-bit effect addresses, but an incomplete final
address is also consumed. A successful zero-length USB URB additionally
reads the packet ID before the common parser is called.

Reject the zero-length USB transfer, require the seven-byte joystick and
wheel prefixes and the two-byte status prefix, and consume only complete
status-tail addresses.

Signed-off-by: Pengpeng Hou <pengpeng@iscas.ac.cn>
Link: https://patch.msgid.link/20260720115018.75045-1-pengpeng@iscas.ac.cn
Cc: stable@vger.kernel.org
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
drivers/input/joystick/iforce/iforce-packets.c
drivers/input/joystick/iforce/iforce-usb.c

index effa76bfd8f9a1fa017a58c32e84cc0f4fab05b9..01fee14054fb230a16a22c4b44480a8740be2aa8 100644 (file)
@@ -155,6 +155,9 @@ void iforce_process_packet(struct iforce *iforce,
        switch (packet_id) {
 
        case 0x01:      /* joystick position data */
+               if (len < 7)
+                       break;
+
                input_report_abs(dev, ABS_X,
                                 (__s16) get_unaligned_le16(data));
                input_report_abs(dev, ABS_Y,
@@ -170,6 +173,9 @@ void iforce_process_packet(struct iforce *iforce,
                break;
 
        case 0x03:      /* wheel position data */
+               if (len < 7)
+                       break;
+
                input_report_abs(dev, ABS_WHEEL,
                                 (__s16) get_unaligned_le16(data));
                input_report_abs(dev, ABS_GAS,   255 - data[2]);
@@ -181,6 +187,9 @@ void iforce_process_packet(struct iforce *iforce,
                break;
 
        case 0x02:      /* status report */
+               if (len < 2)
+                       break;
+
                input_report_key(dev, BTN_DEAD, data[0] & 0x02);
                input_sync(dev);
 
@@ -200,7 +209,7 @@ void iforce_process_packet(struct iforce *iforce,
                        }
                }
 
-               for (j = 3; j < len; j += 2)
+               for (j = 3; j + sizeof(u16) <= len; j += sizeof(u16))
                        mark_core_as_ready(iforce, get_unaligned_le16(data + j));
 
                break;
index 0482eaaecf39a9587a7141f59a8ede21fd2c7934..f04370e4191ea267273353146a793dc3712e95fb 100644 (file)
@@ -158,6 +158,9 @@ static void iforce_usb_irq(struct urb *urb)
                goto exit;
        }
 
+       if (!urb->actual_length)
+               goto exit;
+
        iforce_process_packet(iforce, iforce_usb->data_in[0],
                              iforce_usb->data_in + 1, urb->actual_length - 1);