]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ALSA: usb-mixer: us16x08: validate meter packet indices
authorShipei Qu <qu@darknavy.com>
Wed, 17 Dec 2025 02:46:30 +0000 (10:46 +0800)
committerTakashi Iwai <tiwai@suse.de>
Wed, 17 Dec 2025 09:02:22 +0000 (10:02 +0100)
get_meter_levels_from_urb() parses the 64-byte meter packets sent by
the device and fills the per-channel arrays meter_level[],
comp_level[] and master_level[] in struct snd_us16x08_meter_store.

Currently the function derives the channel index directly from the
meter packet (MUB2(meter_urb, s) - 1) and uses it to index those
arrays without validating the range. If the packet contains a
negative or out-of-range channel number, the driver may write past
the end of these arrays.

Introduce a local channel variable and validate it before updating the
arrays. We reject negative indices, limit meter_level[] and
comp_level[] to SND_US16X08_MAX_CHANNELS, and guard master_level[]
updates with ARRAY_SIZE(master_level).

Fixes: d2bb390a2081 ("ALSA: usb-audio: Tascam US-16x08 DSP mixer quirk")
Reported-by: DARKNAVY (@DarkNavyOrg) <vr@darknavy.com>
Closes: https://lore.kernel.org/tencent_21C112743C44C1A2517FF219@qq.com
Signed-off-by: Shipei Qu <qu@darknavy.com>
Link: https://patch.msgid.link/20251217024630.59576-1-qu@darknavy.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
sound/usb/mixer_us16x08.c

index 1c5712c31f5e2033dab09526c3102bf1271c1351..f9df40730effd16a12e7d734a70e872c9f790926 100644 (file)
@@ -655,17 +655,25 @@ static void get_meter_levels_from_urb(int s,
        u8 *meter_urb)
 {
        int val = MUC2(meter_urb, s) + (MUC3(meter_urb, s) << 8);
+       int ch = MUB2(meter_urb, s) - 1;
+
+       if (ch < 0)
+               return;
 
        if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
                MUA2(meter_urb, s) == 0x04 && MUB0(meter_urb, s) == 0x62) {
-               if (MUC0(meter_urb, s) == 0x72)
-                       store->meter_level[MUB2(meter_urb, s) - 1] = val;
-               if (MUC0(meter_urb, s) == 0xb2)
-                       store->comp_level[MUB2(meter_urb, s) - 1] = val;
+               if (ch < SND_US16X08_MAX_CHANNELS) {
+                       if (MUC0(meter_urb, s) == 0x72)
+                               store->meter_level[ch] = val;
+                       if (MUC0(meter_urb, s) == 0xb2)
+                               store->comp_level[ch] = val;
+               }
        }
        if (MUA0(meter_urb, s) == 0x61 && MUA1(meter_urb, s) == 0x02 &&
-               MUA2(meter_urb, s) == 0x02 && MUB0(meter_urb, s) == 0x62)
-               store->master_level[MUB2(meter_urb, s) - 1] = val;
+               MUA2(meter_urb, s) == 0x02 && MUB0(meter_urb, s) == 0x62) {
+               if (ch < ARRAY_SIZE(store->master_level))
+                       store->master_level[ch] = val;
+       }
 }
 
 /* Function to retrieve current meter values from the device.