Commit 57f87706 authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: usb-audio: More validations of descriptor units



Introduce a new helper to validate each audio descriptor unit before
and check the unit before actually accessing it.  This should harden
against the OOB access cases with malformed descriptors that have been
recently frequently reported by fuzzers.

The existing descriptor checks are still kept although they become
superfluous after this patch.  They'll be cleaned up eventually
later.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent f9f0e9ed
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -16,7 +16,8 @@ snd-usb-audio-objs := card.o \
			power.o \
			proc.o \
			quirks.o \
			stream.o
			stream.o \
			validate.o

snd-usb-audio-$(CONFIG_SND_USB_AUDIO_USE_MEDIA_CONTROLLER) += media.o

+4 −0
Original line number Diff line number Diff line
@@ -31,4 +31,8 @@ static inline int snd_usb_ctrl_intf(struct snd_usb_audio *chip)
	return get_iface_desc(chip->ctrl_intf)->bInterfaceNumber;
}

/* in validate.c */
bool snd_usb_validate_audio_desc(void *p, int protocol);
bool snd_usb_validate_midi_desc(void *p);

#endif /* __USBAUDIO_HELPER_H */
+10 −0
Original line number Diff line number Diff line
@@ -785,6 +785,8 @@ static int __check_input_term(struct mixer_build *state, int id,
		p1 = find_audio_control_unit(state, id);
		if (!p1)
			break;
		if (!snd_usb_validate_audio_desc(p1, protocol))
			break; /* bad descriptor */

		hdr = p1;
		term->id = id;
@@ -2775,6 +2777,11 @@ static int parse_audio_unit(struct mixer_build *state, int unitid)
		return -EINVAL;
	}

	if (!snd_usb_validate_audio_desc(p1, protocol)) {
		usb_audio_dbg(state->chip, "invalid unit %d\n", unitid);
		return 0; /* skip invalid unit */
	}

	if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) {
		switch (p1[2]) {
		case UAC_INPUT_TERMINAL:
@@ -3145,6 +3152,9 @@ static int snd_usb_mixer_controls(struct usb_mixer_interface *mixer)
	while ((p = snd_usb_find_csint_desc(mixer->hostif->extra,
					    mixer->hostif->extralen,
					    p, UAC_OUTPUT_TERMINAL)) != NULL) {
		if (!snd_usb_validate_audio_desc(p, mixer->protocol))
			continue; /* skip invalid descriptor */

		if (mixer->protocol == UAC_VERSION_1) {
			struct uac1_output_terminal_descriptor *desc = p;

+2 −0
Original line number Diff line number Diff line
@@ -31,6 +31,8 @@ snd_usb_find_power_domain(struct usb_host_interface *ctrl_iface,
		struct uac3_power_domain_descriptor *pd_desc = p;
		int i;

		if (!snd_usb_validate_audio_desc(p, UAC_VERSION_3))
			continue;
		for (i = 0; i < pd_desc->bNrEntities; i++) {
			if (pd_desc->baEntityID[i] == id) {
				pd->pd_id = pd_desc->bPowerDomainID;
+3 −0
Original line number Diff line number Diff line
@@ -248,6 +248,9 @@ static int create_yamaha_midi_quirk(struct snd_usb_audio *chip,
					NULL, USB_MS_MIDI_OUT_JACK);
	if (!injd && !outjd)
		return -ENODEV;
	if (!snd_usb_validate_midi_desc(injd) ||
	    !snd_usb_validate_midi_desc(outjd))
		return -ENODEV;
	if (injd && (injd->bLength < 5 ||
		     (injd->bJackType != USB_MS_EMBEDDED &&
		      injd->bJackType != USB_MS_EXTERNAL)))
Loading