A bogus device can provide a clock selector descriptor that contains a
bNrInPins that is larger than the actual size of baCSourceID. This can
lead to out-of-bound reads in __uac_clock_find_source. These out-of-bound
values can be leaked back to the device via the uac_clock_selector_get_val
calls.
Fixes: 79f920fbff56 ("ALSA: usb-audio: parse clock topology of UAC2 devices")
CC: stable@xxxxxxxxxx
Signed-off-by: Benoît Sevens <bsevens@xxxxxxxxxx>
---
sound/usb/clock.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index 8f85200292f3..94fb628f116e 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -270,7 +270,7 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
union uac23_clock_source_desc *source;
union uac23_clock_selector_desc *selector;
union uac23_clock_multiplier_desc *multiplier;
- int ret, i, cur, err, pins, clock_id;
+ int ret, i, cur, err, length, pins, clock_id;
const u8 *sources;
int proto = fmt->protocol;
bool readable, writeable;
@@ -301,11 +301,19 @@ static int __uac_clock_find_source(struct snd_usb_audio *chip,
selector = snd_usb_find_clock_selector(chip, entity_id, fmt);
if (selector) {
+ length = GET_VAL(selector, proto, bLength);
pins = GET_VAL(selector, proto, bNrInPins);
clock_id = GET_VAL(selector, proto, bClockID);
sources = GET_VAL(selector, proto, baCSourceID);
cur = 0;
+ if (length < sizeof(selector) + pins) {
+ usb_audio_err(chip,
+ "%s(): invalid number of input pins for descriptor size, id %d\n",
+ __func__, clock_id);
+ return -EINVAL;
+ }
+
if (proto == UAC_VERSION_3)
bmControls = le32_to_cpu(*(__le32 *)(&selector->v3.baCSourceID[0] + pins));
else
--
2.47.0.338.g60cca15819-goog
[Index of Archives]
[Pulseaudio]
[Linux Audio Users]
[ALSA Devel]
[Fedora Desktop]
[Fedora SELinux]
[Big List of Linux Books]
[Yosemite News]
[KDE Users]