Skip to content

Commit ae17b3b

Browse files
tiwaigregkh
authored andcommitted
ALSA: usb-audio: Validate UAC3 cluster segment descriptors
commit ecfd411 upstream. UAC3 class segment descriptors need to be verified whether their sizes match with the declared lengths and whether they fit with the allocated buffer sizes, too. Otherwise malicious firmware may lead to the unexpected OOB accesses. Fixes: 11785ef ("ALSA: usb-audio: Initial Power Domain support") Reported-and-tested-by: Youngjun Lee <[email protected]> Cc: <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Takashi Iwai <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent cd08d39 commit ae17b3b

File tree

1 file changed

+22
-3
lines changed

1 file changed

+22
-3
lines changed

sound/usb/stream.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,20 +341,28 @@ snd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor
341341

342342
len = le16_to_cpu(cluster->wLength);
343343
c = 0;
344-
p += sizeof(struct uac3_cluster_header_descriptor);
344+
p += sizeof(*cluster);
345+
len -= sizeof(*cluster);
345346

346-
while (((p - (void *)cluster) < len) && (c < channels)) {
347+
while (len > 0 && (c < channels)) {
347348
struct uac3_cluster_segment_descriptor *cs_desc = p;
348349
u16 cs_len;
349350
u8 cs_type;
350351

352+
if (len < sizeof(*p))
353+
break;
351354
cs_len = le16_to_cpu(cs_desc->wLength);
355+
if (len < cs_len)
356+
break;
352357
cs_type = cs_desc->bSegmentType;
353358

354359
if (cs_type == UAC3_CHANNEL_INFORMATION) {
355360
struct uac3_cluster_information_segment_descriptor *is = p;
356361
unsigned char map;
357362

363+
if (cs_len < sizeof(*is))
364+
break;
365+
358366
/*
359367
* TODO: this conversion is not complete, update it
360368
* after adding UAC3 values to asound.h
@@ -456,6 +464,7 @@ snd_pcm_chmap_elem *convert_chmap_v3(struct uac3_cluster_header_descriptor
456464
chmap->map[c++] = map;
457465
}
458466
p += cs_len;
467+
len -= cs_len;
459468
}
460469

461470
if (channels < c)
@@ -880,7 +889,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
880889
u64 badd_formats = 0;
881890
unsigned int num_channels;
882891
struct audioformat *fp;
883-
u16 cluster_id, wLength;
892+
u16 cluster_id, wLength, cluster_wLength;
884893
int clock = 0;
885894
int err;
886895

@@ -1010,6 +1019,16 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
10101019
return ERR_PTR(-EIO);
10111020
}
10121021

1022+
cluster_wLength = le16_to_cpu(cluster->wLength);
1023+
if (cluster_wLength < sizeof(*cluster) ||
1024+
cluster_wLength > wLength) {
1025+
dev_err(&dev->dev,
1026+
"%u:%d : invalid Cluster Descriptor size\n",
1027+
iface_no, altno);
1028+
kfree(cluster);
1029+
return ERR_PTR(-EIO);
1030+
}
1031+
10131032
num_channels = cluster->bNrChannels;
10141033
chmap = convert_chmap_v3(cluster);
10151034
kfree(cluster);

0 commit comments

Comments
 (0)