mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-09 07:23:14 +00:00
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: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
2a4340c577
commit
738d9edcfd
@ -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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
rep->out = ep;
|
rep->out = ep;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error:
|
||||||
|
snd_usbmidi_out_endpoint_delete(ep);
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
Reference in New Issue
Block a user