aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/usb/gspca
diff options
context:
space:
mode:
authorEzequiel Garcia <ezequiel@collabora.com>2018-05-23 16:13:48 -0400
committerMauro Carvalho Chehab <mchehab+samsung@kernel.org>2018-05-28 16:05:03 -0400
commit6992effe5344ceba1c53fd1a062df57e820b27cd (patch)
tree8c1fe015adc7dd0a813ffe2eb9c2a344ceabb9e1 /drivers/media/usb/gspca
parentdf95e82f6b0db20615cf249aec653bcd79ea2b59 (diff)
media: gspca: Kill all URBs before releasing any of them
Some subdrivers access the gspca_dev->urb array in the completion handler. To prevent use-after-free (actually, NULL dereferences) we need to synchronously kill all the URBs before we release them. In particular, this is currently the case for drivers such as sn9c20x and sonixj, which access the gspca_dev->urb[0] in the context of completion handler for *any* of the URBs. This commit changes the destroy_urb implementation, so it kills all URBs first, and then proceed to set the URBs to NULL in the array and release them. Signed-off-by: Ezequiel Garcia <ezequiel@collabora.com> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Diffstat (limited to 'drivers/media/usb/gspca')
-rw-r--r--drivers/media/usb/gspca/gspca.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index a72799666417..57aa521e16b1 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -472,13 +472,20 @@ static void destroy_urbs(struct gspca_dev *gspca_dev)
472 unsigned int i; 472 unsigned int i;
473 473
474 gspca_dbg(gspca_dev, D_STREAM, "kill transfer\n"); 474 gspca_dbg(gspca_dev, D_STREAM, "kill transfer\n");
475
476 /* Killing all URBs guarantee that no URB completion
477 * handler is running. Therefore, there shouldn't
478 * be anyone trying to access gspca_dev->urb[i]
479 */
480 for (i = 0; i < MAX_NURBS; i++)
481 usb_kill_urb(gspca_dev->urb[i]);
482
483 gspca_dbg(gspca_dev, D_STREAM, "releasing urbs\n");
475 for (i = 0; i < MAX_NURBS; i++) { 484 for (i = 0; i < MAX_NURBS; i++) {
476 urb = gspca_dev->urb[i]; 485 urb = gspca_dev->urb[i];
477 if (urb == NULL) 486 if (!urb)
478 break; 487 continue;
479
480 gspca_dev->urb[i] = NULL; 488 gspca_dev->urb[i] = NULL;
481 usb_kill_urb(urb);
482 usb_free_coherent(gspca_dev->dev, 489 usb_free_coherent(gspca_dev->dev,
483 urb->transfer_buffer_length, 490 urb->transfer_buffer_length,
484 urb->transfer_buffer, 491 urb->transfer_buffer,