Skip to content

Commit

Permalink
ALSA: usb-audio: Add sanity checks for invalid EPs
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Takashi Iwai committed Oct 11, 2017
1 parent 2a4340c commit 738d9ed
Showing 1 changed file with 30 additions and 8 deletions.
38 changes: 30 additions & 8 deletions sound/usb/midi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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)
Expand All @@ -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,
Expand All @@ -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;
}

/*
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down Expand Up @@ -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,
Expand All @@ -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;
}

Expand All @@ -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;
}

/*
Expand Down

0 comments on commit 738d9ed

Please sign in to comment.