Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 738d9edc authored by Takashi Iwai's avatar Takashi Iwai
Browse files

ALSA: usb-audio: Add sanity checks for invalid EPs



USB-audio driver may set up a URB containing the fixed EP without
validating its presence for some non-class-compliant devices.  This
may end up with an oops-like kernel warning when submitted.

For avoiding it, this patch adds the call of the new sanity-check
helper for URBs.  The checks are needed only for MIDI I/O as the other
places have already some other checks.

Signed-off-by: default avatarTakashi Iwai <tiwai@suse.de>
parent 2a4340c5
Loading
Loading
Loading
Loading
+30 −8
Original line number Diff line number Diff line
@@ -1282,6 +1282,7 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
	unsigned int pipe;
	int length;
	unsigned int i;
	int err;

	rep->in = NULL;
	ep = kzalloc(sizeof(*ep), GFP_KERNEL);
@@ -1292,8 +1293,8 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
	for (i = 0; i < INPUT_URBS; ++i) {
		ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
		if (!ep->urbs[i]) {
			snd_usbmidi_in_endpoint_delete(ep);
			return -ENOMEM;
			err = -ENOMEM;
			goto error;
		}
	}
	if (ep_info->in_interval)
@@ -1305,8 +1306,8 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
		buffer = usb_alloc_coherent(umidi->dev, length, GFP_KERNEL,
					    &ep->urbs[i]->transfer_dma);
		if (!buffer) {
			snd_usbmidi_in_endpoint_delete(ep);
			return -ENOMEM;
			err = -ENOMEM;
			goto error;
		}
		if (ep_info->in_interval)
			usb_fill_int_urb(ep->urbs[i], umidi->dev,
@@ -1318,10 +1319,20 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
					  pipe, buffer, length,
					  snd_usbmidi_in_urb_complete, ep);
		ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
		err = usb_urb_ep_type_check(ep->urbs[i]);
		if (err < 0) {
			dev_err(&umidi->dev->dev, "invalid MIDI in EP %x\n",
				ep_info->in_ep);
			goto error;
		}
	}

	rep->in = ep;
	return 0;

 error:
	snd_usbmidi_in_endpoint_delete(ep);
	return -ENOMEM;
}

/*
@@ -1357,6 +1368,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
	unsigned int i;
	unsigned int pipe;
	void *buffer;
	int err;

	rep->out = NULL;
	ep = kzalloc(sizeof(*ep), GFP_KERNEL);
@@ -1367,8 +1379,8 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
	for (i = 0; i < OUTPUT_URBS; ++i) {
		ep->urbs[i].urb = usb_alloc_urb(0, GFP_KERNEL);
		if (!ep->urbs[i].urb) {
			snd_usbmidi_out_endpoint_delete(ep);
			return -ENOMEM;
			err = -ENOMEM;
			goto error;
		}
		ep->urbs[i].ep = ep;
	}
@@ -1406,8 +1418,8 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
					    ep->max_transfer, GFP_KERNEL,
					    &ep->urbs[i].urb->transfer_dma);
		if (!buffer) {
			snd_usbmidi_out_endpoint_delete(ep);
			return -ENOMEM;
			err = -ENOMEM;
			goto error;
		}
		if (ep_info->out_interval)
			usb_fill_int_urb(ep->urbs[i].urb, umidi->dev,
@@ -1419,6 +1431,12 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
					  pipe, buffer, ep->max_transfer,
					  snd_usbmidi_out_urb_complete,
					  &ep->urbs[i]);
		err = usb_urb_ep_type_check(ep->urbs[i].urb);
		if (err < 0) {
			dev_err(&umidi->dev->dev, "invalid MIDI out EP %x\n",
				ep_info->out_ep);
			goto error;
		}
		ep->urbs[i].urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
	}

@@ -1437,6 +1455,10 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,

	rep->out = ep;
	return 0;

 error:
	snd_usbmidi_out_endpoint_delete(ep);
	return err;
}

/*