From: Takashi Iwai <tiwai@suse.de>
To: linux-sound@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Subject: [PATCH v3 4/8] ALSA: usb-audio: Fix invalid UAC2/3 mixer unit matrix evaluation
Date: Wed, 7 Oct 2026 19:20:40 +0200 [thread overview]
Message-ID: <20261007172051.13240-5-tiwai@suse.de> (raw)
In-Reply-To: <20261007172051.13240-1-tiwai@suse.de>
The bitmap matrix in the mixer unit descriptor for UAC2 and UAC3 has
rather the size of input-pins x output-pins, while the current
USB-audio driver code wrongly assumes the UAC1 bitmap matrix size,
which is input-channels x output-pins. That is, when input pins have
multiple channels, the column size differs and it leads to the
accesses at a wrong position.
This patch corrects the access of the bitmap matrix for UAC2/UAC3.
For making the code cleaner, split the parser to UAC1 and UAC2/3, too.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Fixes: 23caaf19b11e ("ALSA: usb-mixer: Add support for Audio Class v2.0")
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
sound/usb/mixer.c | 112 ++++++++++++++++++++++++++++++++--------------
1 file changed, 78 insertions(+), 34 deletions(-)
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index b6e22244e03a..9d8007ea95d5 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -2377,7 +2377,7 @@ static bool mixer_bitmap_overflow(struct uac_mixer_unit_descriptor *desc,
*/
static void build_mixer_unit_ctl(struct mixer_build *state,
struct uac_mixer_unit_descriptor *desc,
- int in_pin, int in_ch, int num_outs,
+ int in_ch, int num_outs,
int unitid, struct usb_audio_term *iterm)
{
struct usb_mixer_elem_info *cval;
@@ -2472,34 +2472,13 @@ static int parse_audio_input_terminal(struct mixer_build *state, int unitid,
/*
* parse a mixer unit
*/
-static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
- void *raw_desc)
+/* UAC1 mixer unit */
+static int parse_audio_mixer_unit_v1(struct mixer_build *state, int unitid,
+ int input_pins, int num_outs,
+ struct uac_mixer_unit_descriptor *desc)
{
- struct uac_mixer_unit_descriptor *desc = raw_desc;
struct usb_audio_term iterm;
- int input_pins, num_ins, num_outs;
- int pin, ich, err;
-
- err = uac_mixer_unit_get_channels(state, desc);
- if (err < 0) {
- usb_audio_err(state->chip,
- "invalid MIXER UNIT descriptor %d\n",
- unitid);
- return err;
- }
-
- num_outs = err;
- input_pins = desc->bNrInPins;
-
- if (state->mixer->protocol == UAC_VERSION_2 ||
- state->mixer->protocol == UAC_VERSION_3) {
- if (input_pins * num_outs > 256) {
- usb_audio_err(state->chip,
- "invalid channels for MIXER UNIT %d: input=%d, output=%d\n",
- unitid, input_pins, num_outs);
- return -EINVAL;
- }
- }
+ int num_ins, pin, ich, och, err;
num_ins = 0;
ich = 0;
@@ -2518,25 +2497,90 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
num_ins, num_outs))
break;
for (; ich < num_ins; ich++) {
- int och, ich_has_controls = 0;
-
for (och = 0; och < num_outs; och++) {
__u8 *c = uac_mixer_unit_bmControls(desc,
state->mixer->protocol);
- if (check_matrix_bitmap(c, ich, och, num_outs)) {
- ich_has_controls = 1;
+ if (check_matrix_bitmap(c, ich, och, num_outs))
break;
- }
}
- if (ich_has_controls)
- build_mixer_unit_ctl(state, desc, pin, ich, num_outs,
+ if (och < num_outs)
+ build_mixer_unit_ctl(state, desc, ich, num_outs,
unitid, &iterm);
}
}
return 0;
}
+/* UAC2/UAC3 mixer unit */
+static int parse_audio_mixer_unit_v2(struct mixer_build *state, int unitid,
+ int input_pins, int num_outs,
+ struct uac_mixer_unit_descriptor *desc)
+{
+ struct usb_audio_term iterm;
+ int pin, och, err;
+
+ if (input_pins * num_outs > 256 ||
+ mixer_bitmap_overflow(desc, state->mixer->protocol,
+ input_pins, num_outs)) {
+ usb_audio_err(state->chip,
+ "invalid channels for MIXER UNIT %d: input=%d, output=%d\n",
+ unitid, input_pins, num_outs);
+ return -EINVAL;
+ }
+
+ for (pin = 0; pin < input_pins; pin++) {
+ err = parse_audio_unit(state, desc->baSourceID[pin]);
+ if (err < 0)
+ continue;
+ if (!num_outs)
+ continue;
+ err = check_input_term(state, desc->baSourceID[pin], &iterm);
+ if (err < 0)
+ return err;
+
+ for (och = 0; och < num_outs; och++) {
+ __u8 *c = uac_mixer_unit_bmControls(desc,
+ state->mixer->protocol);
+
+ if (check_matrix_bitmap(c, pin, och, num_outs))
+ break;
+ }
+ if (och < num_outs)
+ build_mixer_unit_ctl(state, desc, pin, num_outs,
+ unitid, &iterm);
+ }
+ return 0;
+}
+
+static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
+ void *raw_desc)
+{
+ struct uac_mixer_unit_descriptor *desc = raw_desc;
+ int num_outs;
+
+ num_outs = uac_mixer_unit_get_channels(state, desc);
+ if (num_outs < 0) {
+ usb_audio_err(state->chip,
+ "invalid MIXER UNIT descriptor %d\n",
+ unitid);
+ return num_outs;
+ }
+
+ switch (state->mixer->protocol) {
+ case UAC_VERSION_1:
+ default:
+ return parse_audio_mixer_unit_v1(state, unitid,
+ desc->bNrInPins, num_outs,
+ desc);
+ case UAC_VERSION_2:
+ case UAC_VERSION_3:
+ return parse_audio_mixer_unit_v2(state, unitid,
+ desc->bNrInPins, num_outs,
+ desc);
+ }
+}
+
/*
* Processing Unit / Extension Unit
*/
--
2.55.0
next prev parent reply other threads:[~2026-10-07 17:20 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-07 17:20 [PATCH v3 0/8] ALSA: Fix some bugs reported by Sashiko Takashi Iwai
2026-10-07 17:20 ` [PATCH v3 1/8] ALSA: seq: Drop the bogus RCU guard from clientptr() Takashi Iwai
2026-10-07 17:20 ` [PATCH v3 2/8] ALSA: pcm: Fix TOCTOU state overwrite in snd_pcm_drop() Takashi Iwai
2026-10-07 17:20 ` [PATCH v3 3/8] ALSA: hda: Fix potential UAF for gating jack Takashi Iwai
2026-10-07 17:20 ` Takashi Iwai [this message]
2026-10-07 17:20 ` [PATCH v3 5/8] ALSA: usb-audio: Fix data race at mixer_ctl_feature_info() Takashi Iwai
2026-10-07 17:20 ` [PATCH v3 6/8] ALSA: pcmtest: Fix a bogus pointer read in snd_pcmtst_pcm_pointer() Takashi Iwai
2026-10-07 17:20 ` [PATCH v3 7/8] ALSA: usb-audio: Fix mixer bitmap cache over 32 channels Takashi Iwai
2026-10-07 17:20 ` [PATCH v3 8/8] ALSA: core: Add missing barriers for power_ref vs card->shutdown Takashi Iwai
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261007172051.13240-5-tiwai@suse.de \
--to=tiwai@suse.de \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®