[PATCH v3] ALSA: usb-mixer: us16x08: validate meter packet indices

Shipei Qu posted 1 patch 1 day, 11 hours ago
sound/usb/mixer_us16x08.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
[PATCH v3] ALSA: usb-mixer: us16x08: validate meter packet indices
Posted by Shipei Qu 1 day, 11 hours ago
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).

Reported-by: DARKNAVY (@DarkNavyOrg) <vr@darknavy.com>
Signed-off-by: Shipei Qu <qu@darknavy.com>
---
v3: rephrase commit description
v2: resend with properly formatted diff

 sound/usb/mixer_us16x08.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c
index 1c5712c31..f9df40730 100644
--- a/sound/usb/mixer_us16x08.c
+++ b/sound/usb/mixer_us16x08.c
@@ -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.
-- 
2.45.1
Re: [PATCH v3] ALSA: usb-mixer: us16x08: validate meter packet indices
Posted by Takashi Iwai 1 day, 4 hours ago
On Wed, 17 Dec 2025 03:46:30 +0100,
Shipei Qu wrote:
> 
> 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).
> 
> Reported-by: DARKNAVY (@DarkNavyOrg) <vr@darknavy.com>
> Signed-off-by: Shipei Qu <qu@darknavy.com>

Applied now.  Thanks.


Takashi