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

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


commit 035ffabe064c59845c3edb92a1b776701d0dd556
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                                        |   11 ++-
 ...e-induced-crash-in-uvc_video_clock_update.patch |  113 ++++++++++++++++++++
 2 files changed, 123 insertions(+), 1 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index f51b2d1..76d4dd5 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -54,7 +54,7 @@ Summary: The Linux kernel
 # For non-released -rc kernels, this will be appended after the rcX and
 # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
 #
-%global baserelease 1
+%global baserelease 2
 %global fedora_build %{baserelease}
 
 # base_sublevel is the kernel version we're starting with and patching
@@ -767,6 +767,9 @@ Patch21351: x86-add-io_apic_ops-to-allow-interception.patch
 Patch21352: x86-apic_ops-Replace-apic_ops-with-x86_apic_ops.patch
 Patch21353: xen-x86-Implement-x86_apic_ops.patch
 
+#rhbz 806433
+Patch21360: uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch
+
 #rhbz 770476
 Patch21370: iwlegacy-do-not-nulify-il-vif-on-reset.patch
 Patch21371: iwlwifi-do-not-nulify-ctx-vif-on-reset.patch
@@ -1508,6 +1511,9 @@ ApplyPatch nfs-Fix-length-of-buffer-copied-in-__nfs4_get_acl_uncached.patch
 #rhbz 808207 CVE-2012-1601
 ApplyPatch KVM-Ensure-all-vcpus-are-consistent-with-in-kernel-i.patch
 
+#rhbz 806433
+ApplyPatch uvcvideo-Fix-race-induced-crash-in-uvc_video_clock_update.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -2347,6 +2353,9 @@ fi
 #    '-'      |  |
 #              '-'
 %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 Dave Jones <davej at redhat.com> 3.3.1-1
 - Linux 3.3.1
 
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