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

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
...@@ -1282,6 +1282,7 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi, ...@@ -1282,6 +1282,7 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
unsigned int pipe; unsigned int pipe;
int length; int length;
unsigned int i; unsigned int i;
int err;
rep->in = NULL; rep->in = NULL;
ep = kzalloc(sizeof(*ep), GFP_KERNEL); ep = kzalloc(sizeof(*ep), GFP_KERNEL);
...@@ -1292,8 +1293,8 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi, ...@@ -1292,8 +1293,8 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
for (i = 0; i < INPUT_URBS; ++i) { for (i = 0; i < INPUT_URBS; ++i) {
ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL); ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
if (!ep->urbs[i]) { if (!ep->urbs[i]) {
snd_usbmidi_in_endpoint_delete(ep); err = -ENOMEM;
return -ENOMEM; goto error;
} }
} }
if (ep_info->in_interval) if (ep_info->in_interval)
...@@ -1305,8 +1306,8 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi, ...@@ -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, buffer = usb_alloc_coherent(umidi->dev, length, GFP_KERNEL,
&ep->urbs[i]->transfer_dma); &ep->urbs[i]->transfer_dma);
if (!buffer) { if (!buffer) {
snd_usbmidi_in_endpoint_delete(ep); err = -ENOMEM;
return -ENOMEM; goto error;
} }
if (ep_info->in_interval) if (ep_info->in_interval)
usb_fill_int_urb(ep->urbs[i], umidi->dev, 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, ...@@ -1318,10 +1319,20 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
pipe, buffer, length, pipe, buffer, length,
snd_usbmidi_in_urb_complete, ep); snd_usbmidi_in_urb_complete, ep);
ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; 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; rep->in = ep;
return 0; 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, ...@@ -1357,6 +1368,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
unsigned int i; unsigned int i;
unsigned int pipe; unsigned int pipe;
void *buffer; void *buffer;
int err;
rep->out = NULL; rep->out = NULL;
ep = kzalloc(sizeof(*ep), GFP_KERNEL); ep = kzalloc(sizeof(*ep), GFP_KERNEL);
...@@ -1367,8 +1379,8 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi, ...@@ -1367,8 +1379,8 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
for (i = 0; i < OUTPUT_URBS; ++i) { for (i = 0; i < OUTPUT_URBS; ++i) {
ep->urbs[i].urb = usb_alloc_urb(0, GFP_KERNEL); ep->urbs[i].urb = usb_alloc_urb(0, GFP_KERNEL);
if (!ep->urbs[i].urb) { if (!ep->urbs[i].urb) {
snd_usbmidi_out_endpoint_delete(ep); err = -ENOMEM;
return -ENOMEM; goto error;
} }
ep->urbs[i].ep = ep; ep->urbs[i].ep = ep;
} }
...@@ -1406,8 +1418,8 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi, ...@@ -1406,8 +1418,8 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
ep->max_transfer, GFP_KERNEL, ep->max_transfer, GFP_KERNEL,
&ep->urbs[i].urb->transfer_dma); &ep->urbs[i].urb->transfer_dma);
if (!buffer) { if (!buffer) {
snd_usbmidi_out_endpoint_delete(ep); err = -ENOMEM;
return -ENOMEM; goto error;
} }
if (ep_info->out_interval) if (ep_info->out_interval)
usb_fill_int_urb(ep->urbs[i].urb, umidi->dev, 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, ...@@ -1419,6 +1431,12 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
pipe, buffer, ep->max_transfer, pipe, buffer, ep->max_transfer,
snd_usbmidi_out_urb_complete, snd_usbmidi_out_urb_complete,
&ep->urbs[i]); &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; 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, ...@@ -1437,6 +1455,10 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
rep->out = ep; rep->out = ep;
return 0; return 0;
error:
snd_usbmidi_out_endpoint_delete(ep);
return err;
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment