diff --git a/kernel.spec b/kernel.spec index d933f6af0..0f90da2e1 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 +- Fix crash in uvc_video_clock_update from Laurent Pinchart (rhbz 806433) + * Mon Apr 02 2012 Justin M. Forbes - 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 000000000..5f2a1c006 --- /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; + }