[kernel] Fix crash in uvc_video_clock_update from Laurent Pinchart (rhbz 806433)

Josh Boyer jwboyer at fedoraproject.org
Tue Apr 3 17:58:21 UTC 2012


commit 8390bec6eae6477511ac3d93f37d65e88fbd3b28
Author: Josh Boyer <jwboyer at redhat.com>
Date:   Tue Apr 3 12:55:28 2012 -0400

    Fix crash in uvc_video_clock_update from Laurent Pinchart (rhbz 806433)

 kernel.spec                                        |    9 ++
 ...e-induced-crash-in-uvc_video_clock_update.patch |  113 ++++++++++++++++++++
 2 files changed, 122 insertions(+), 0 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index d933f6a..0f90da2 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -738,6 +738,9 @@ Patch21305: mac80211-fix-possible-tid_rx-reorder_timer-use-after-free.patch
 #rhbz 804957 CVE-2012-1568
 Patch21306: shlib_base_randomize.patch
 
+#rhbz 806433
+Patch21360: uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch
+
 Patch21400: unhandled-irqs-switch-to-polling.patch
 
 Patch22000: weird-root-dentry-name-debug.patch
@@ -1430,6 +1433,9 @@ ApplyPatch weird-root-dentry-name-debug.patch
 #Highbank clock functions
 ApplyPatch highbank-export-clock-functions.patch 
 
+#rhbz 806433
+ApplyPatch uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -2285,6 +2291,9 @@ fi
 #                 ||----w |
 #                 ||     ||
 %changelog
+* Tue Apr 03 2012 Josh Boyer <jwboyer at redhat.com>
+- Fix crash in uvc_video_clock_update from Laurent Pinchart (rhbz 806433)
+
 * Mon Apr 02 2012 Justin M. Forbes <jforbes at redhat.com> - 3.4.0-0.rc1.git0.2
 - Fix config since koji preps as noarch
 
diff --git a/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch b/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch
new file mode 100644
index 0000000..5f2a1c0
--- /dev/null
+++ b/uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch
@@ -0,0 +1,113 @@
+@@ -, +, @@ 
+ drivers/media/video/uvc/uvc_video.c |   50 ++++++++++++++++++++++------------
+ 1 files changed, 32 insertions(+), 18 deletions(-)
+--- a/drivers/media/video/uvc/uvc_video.c	
++++ a/drivers/media/video/uvc/uvc_video.c	
+@@ -468,22 +468,30 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
+ 	spin_unlock_irqrestore(&stream->clock.lock, flags);
+ }
+ 
+-static int uvc_video_clock_init(struct uvc_streaming *stream)
++static void uvc_video_clock_reset(struct uvc_streaming *stream)
+ {
+ 	struct uvc_clock *clock = &stream->clock;
+ 
+-	spin_lock_init(&clock->lock);
+ 	clock->head = 0;
+ 	clock->count = 0;
+-	clock->size = 32;
+ 	clock->last_sof = -1;
+ 	clock->sof_offset = -1;
++}
++
++static int uvc_video_clock_init(struct uvc_streaming *stream)
++{
++	struct uvc_clock *clock = &stream->clock;
++
++	spin_lock_init(&clock->lock);
++	clock->size = 32;
+ 
+ 	clock->samples = kmalloc(clock->size * sizeof(*clock->samples),
+ 				 GFP_KERNEL);
+ 	if (clock->samples == NULL)
+ 		return -ENOMEM;
+ 
++	uvc_video_clock_reset(stream);
++
+ 	return 0;
+ }
+ 
+@@ -1424,8 +1432,6 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
+ 
+ 	if (free_buffers)
+ 		uvc_free_urb_buffers(stream);
+-
+-	uvc_video_clock_cleanup(stream);
+ }
+ 
+ /*
+@@ -1555,10 +1561,6 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
+ 
+ 	uvc_video_stats_start(stream);
+ 
+-	ret = uvc_video_clock_init(stream);
+-	if (ret < 0)
+-		return ret;
+-
+ 	if (intf->num_altsetting > 1) {
+ 		struct usb_host_endpoint *best_ep = NULL;
+ 		unsigned int best_psize = 3 * 1024;
+@@ -1683,6 +1685,8 @@ int uvc_video_resume(struct uvc_streaming *stream, int reset)
+ 
+ 	stream->frozen = 0;
+ 
++	uvc_video_clock_reset(stream);
++
+ 	ret = uvc_commit_video(stream, &stream->ctrl);
+ 	if (ret < 0) {
+ 		uvc_queue_enable(&stream->queue, 0);
+@@ -1819,25 +1823,35 @@ int uvc_video_enable(struct uvc_streaming *stream, int enable)
+ 		uvc_uninit_video(stream, 1);
+ 		usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+ 		uvc_queue_enable(&stream->queue, 0);
++		uvc_video_clock_cleanup(stream);
+ 		return 0;
+ 	}
+ 
+-	ret = uvc_queue_enable(&stream->queue, 1);
++	ret = uvc_video_clock_init(stream);
+ 	if (ret < 0)
+ 		return ret;
+ 
++	ret = uvc_queue_enable(&stream->queue, 1);
++	if (ret < 0)
++		goto error_queue;
++
+ 	/* Commit the streaming parameters. */
+ 	ret = uvc_commit_video(stream, &stream->ctrl);
+-	if (ret < 0) {
+-		uvc_queue_enable(&stream->queue, 0);
+-		return ret;
+-	}
++	if (ret < 0)
++		goto error_commit;
+ 
+ 	ret = uvc_init_video(stream, GFP_KERNEL);
+-	if (ret < 0) {
+-		usb_set_interface(stream->dev->udev, stream->intfnum, 0);
+-		uvc_queue_enable(&stream->queue, 0);
+-	}
++	if (ret < 0)
++		goto error_video;
++
++	return 0;
++
++error_video:
++	usb_set_interface(stream->dev->udev, stream->intfnum, 0);
++error_commit:
++	uvc_queue_enable(&stream->queue, 0);
++error_queue:
++	uvc_video_clock_cleanup(stream);
+ 
+ 	return ret;
+ }


More information about the scm-commits mailing list