Skip to content

Commit ecfd411

Browse files
committed
ALSA: usb-audio: Validate UAC3 cluster segment descriptors
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]>
1 parent d832ccb commit ecfd411

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)
@@ -881,7 +890,7 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
881890
u64 badd_formats = 0;
882891
unsigned int num_channels;
883892
struct audioformat *fp;
884-
u16 cluster_id, wLength;
893+
u16 cluster_id, wLength, cluster_wLength;
885894
int clock = 0;
886895
int err;
887896

@@ -1011,6 +1020,16 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
10111020
return ERR_PTR(-EIO);
10121021
}
10131022

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

0 commit comments

Comments
 (0)