aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2017-10-04 11:22:05 -0400
committerTakashi Iwai <tiwai@suse.de>2017-10-11 09:14:51 -0400
commit738d9edcfd44f154924692e54109fb439fcf8bdd (patch)
tree0a1a1681acb0576176c90dca28fac2fa14684d81
parent2a4340c57717162c6bf07a0860d05711d4de994b (diff)
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>
-rw-r--r--sound/usb/midi.c38
1 files changed, 30 insertions, 8 deletions
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index a92e2b2a91ec..7ab25de5ca0a 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -1282,6 +1282,7 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
1282 unsigned int pipe; 1282 unsigned int pipe;
1283 int length; 1283 int length;
1284 unsigned int i; 1284 unsigned int i;
1285 int err;
1285 1286
1286 rep->in = NULL; 1287 rep->in = NULL;
1287 ep = kzalloc(sizeof(*ep), GFP_KERNEL); 1288 ep = kzalloc(sizeof(*ep), GFP_KERNEL);
@@ -1292,8 +1293,8 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
1292 for (i = 0; i < INPUT_URBS; ++i) { 1293 for (i = 0; i < INPUT_URBS; ++i) {
1293 ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL); 1294 ep->urbs[i] = usb_alloc_urb(0, GFP_KERNEL);
1294 if (!ep->urbs[i]) { 1295 if (!ep->urbs[i]) {
1295 snd_usbmidi_in_endpoint_delete(ep); 1296 err = -ENOMEM;
1296 return -ENOMEM; 1297 goto error;
1297 } 1298 }
1298 } 1299 }
1299 if (ep_info->in_interval) 1300 if (ep_info->in_interval)
@@ -1305,8 +1306,8 @@ static int snd_usbmidi_in_endpoint_create(struct snd_usb_midi *umidi,
1305 buffer = usb_alloc_coherent(umidi->dev, length, GFP_KERNEL, 1306 buffer = usb_alloc_coherent(umidi->dev, length, GFP_KERNEL,
1306 &ep->urbs[i]->transfer_dma); 1307 &ep->urbs[i]->transfer_dma);
1307 if (!buffer) { 1308 if (!buffer) {
1308 snd_usbmidi_in_endpoint_delete(ep); 1309 err = -ENOMEM;
1309 return -ENOMEM; 1310 goto error;
1310 } 1311 }
1311 if (ep_info->in_interval) 1312 if (ep_info->in_interval)
1312 usb_fill_int_urb(ep->urbs[i], umidi->dev, 1313 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 pipe, buffer, length, 1319 pipe, buffer, length,
1319 snd_usbmidi_in_urb_complete, ep); 1320 snd_usbmidi_in_urb_complete, ep);
1320 ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP; 1321 ep->urbs[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
1322 err = usb_urb_ep_type_check(ep->urbs[i]);
1323 if (err < 0) {
1324 dev_err(&umidi->dev->dev, "invalid MIDI in EP %x\n",
1325 ep_info->in_ep);
1326 goto error;
1327 }
1321 } 1328 }
1322 1329
1323 rep->in = ep; 1330 rep->in = ep;
1324 return 0; 1331 return 0;
1332
1333 error:
1334 snd_usbmidi_in_endpoint_delete(ep);
1335 return -ENOMEM;
1325} 1336}
1326 1337
1327/* 1338/*
@@ -1357,6 +1368,7 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
1357 unsigned int i; 1368 unsigned int i;
1358 unsigned int pipe; 1369 unsigned int pipe;
1359 void *buffer; 1370 void *buffer;
1371 int err;
1360 1372
1361 rep->out = NULL; 1373 rep->out = NULL;
1362 ep = kzalloc(sizeof(*ep), GFP_KERNEL); 1374 ep = kzalloc(sizeof(*ep), GFP_KERNEL);
@@ -1367,8 +1379,8 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
1367 for (i = 0; i < OUTPUT_URBS; ++i) { 1379 for (i = 0; i < OUTPUT_URBS; ++i) {
1368 ep->urbs[i].urb = usb_alloc_urb(0, GFP_KERNEL); 1380 ep->urbs[i].urb = usb_alloc_urb(0, GFP_KERNEL);
1369 if (!ep->urbs[i].urb) { 1381 if (!ep->urbs[i].urb) {
1370 snd_usbmidi_out_endpoint_delete(ep); 1382 err = -ENOMEM;
1371 return -ENOMEM; 1383 goto error;
1372 } 1384 }
1373 ep->urbs[i].ep = ep; 1385 ep->urbs[i].ep = ep;
1374 } 1386 }
@@ -1406,8 +1418,8 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
1406 ep->max_transfer, GFP_KERNEL, 1418 ep->max_transfer, GFP_KERNEL,
1407 &ep->urbs[i].urb->transfer_dma); 1419 &ep->urbs[i].urb->transfer_dma);
1408 if (!buffer) { 1420 if (!buffer) {
1409 snd_usbmidi_out_endpoint_delete(ep); 1421 err = -ENOMEM;
1410 return -ENOMEM; 1422 goto error;
1411 } 1423 }
1412 if (ep_info->out_interval) 1424 if (ep_info->out_interval)
1413 usb_fill_int_urb(ep->urbs[i].urb, umidi->dev, 1425 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 pipe, buffer, ep->max_transfer, 1431 pipe, buffer, ep->max_transfer,
1420 snd_usbmidi_out_urb_complete, 1432 snd_usbmidi_out_urb_complete,
1421 &ep->urbs[i]); 1433 &ep->urbs[i]);
1434 err = usb_urb_ep_type_check(ep->urbs[i].urb);
1435 if (err < 0) {
1436 dev_err(&umidi->dev->dev, "invalid MIDI out EP %x\n",
1437 ep_info->out_ep);
1438 goto error;
1439 }
1422 ep->urbs[i].urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP; 1440 ep->urbs[i].urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
1423 } 1441 }
1424 1442
@@ -1437,6 +1455,10 @@ static int snd_usbmidi_out_endpoint_create(struct snd_usb_midi *umidi,
1437 1455
1438 rep->out = ep; 1456 rep->out = ep;
1439 return 0; 1457 return 0;
1458
1459 error:
1460 snd_usbmidi_out_endpoint_delete(ep);
1461 return err;
1440} 1462}
1441 1463
1442/* 1464/*