ALSA: caiaq: bound the length in the EP1 input parsers

snd_caiaq_input_read_erp() and snd_caiaq_input_read_io() can be reached
from snd_usb_caiaq_input_dispatch(). They read fixed byte offsets from
the reply buffer without checking the reported length. On a short reply
they decode stale bytes left from a previous, longer report and feed them
to the input layer.

This is not an out-of-bounds access. Every offset is a compile-time
driver constant. The largest is buf[21] in the Maschine ERP case. The
EP1 transfer buffer ep1_in_buf is EP1_BUFSIZE (64) bytes, and the USB
core caps actual_length at 64, so a short reply only reads in-bounds
stale data. Acting on data the device did not send is still wrong, so
bail out per usb_id case when the reply is shorter than the bytes that
case consumes.

  read_erp: AK1 needs 2 bytes, Kore needs 16, Maschine needs 22.
  read_io:  the Kore case needs 5 bytes (buf[4]) and the Traktor Kontrol
            X1 case needs 7 (buf[5]/buf[6]). The preceding key bit loop
            is already bounded by "i < len * 8" and is left untouched.

snd_caiaq_input_read_analog() and snd_usb_caiaq_maschine_dispatch() are
not changed. Their callers already floor the reply length.

Suggested-by: Takashi Iwai <tiwai@suse.com>
Signed-off-by: Maoyi Xie <maoyixie.tju@gmail.com>
Link: https://patch.msgid.link/178176259547.3343534.6659489917322808916@maoyixie.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
Maoyi Xie 2026-06-18 14:03:15 +08:00 committed by Takashi Iwai
parent f7f3f9fd81
commit 58fc1275b3

View File

@ -237,12 +237,16 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *cdev,
switch (cdev->chip.usb_id) {
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
if (len < 2)
return;
i = decode_erp(buf[0], buf[1]);
input_report_abs(input_dev, ABS_X, i);
input_sync(input_dev);
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
if (len < 16)
return;
i = decode_erp(buf[7], buf[5]);
input_report_abs(input_dev, ABS_HAT0X, i);
i = decode_erp(buf[12], buf[14]);
@ -263,6 +267,8 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *cdev,
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
if (len < 22)
return;
/* 4 under the left screen */
input_report_abs(input_dev, ABS_HAT0X, decode_erp(buf[21], buf[20]));
input_report_abs(input_dev, ABS_HAT0Y, decode_erp(buf[15], buf[14]));
@ -308,9 +314,13 @@ static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *cdev,
switch (cdev->chip.usb_id) {
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
if (len < 5)
return;
input_report_abs(cdev->input_dev, ABS_MISC, 255 - buf[4]);
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
if (len < 7)
return;
/* rotary encoders */
input_report_abs(cdev->input_dev, ABS_X, buf[5] & 0xf);
input_report_abs(cdev->input_dev, ABS_Y, buf[5] >> 4);