The patch number 8257 was added via Mauro Carvalho Chehab <[EMAIL PROTECTED]> to http://linuxtv.org/hg/v4l-dvb master development tree.
Kernel patches in this development tree may be modified to be backward compatible with older kernels. Compatibility modifications will be removed before inclusion into the mainstream Kernel If anyone has any objections, please let us know by sending a message to: [EMAIL PROTECTED] ------ From: Laurent Pinchart <[EMAIL PROTECTED]> uvcvideo: Fix possible AB-BA deadlock with videodev_lock and open_mutex The uvcvideo driver's uvc_v4l2_open() method is called from videodev's video_open() function, which means it is called with the videodev_lock mutex held. uvc_v4l2_open() then takes uvc_driver.open_mutex to check dev->state and avoid racing against a device disconnect, which means that open_mutex must nest inside videodev_lock. However uvc_disconnect() takes the open_mutex around setting dev->state and also around putting its device reference. However, if uvc_disconnect() ends up dropping the last reference, it will call uvc_delete(), which calls into the videodev code to unregister its device, and this will end up taking videodev_lock. This opens a (unlikely in practice) window for an AB-BA deadlock and also causes a lockdep warning because of the lock misordering. Fortunately there is no apparent reason to hold open_mutex when doing kref_put() in uvc_disconnect(): if uvc_v4l2_open() runs before the state is set to UVC_DEV_DISCONNECTED, then it will take another reference to the device and kref_put() won't call uvc_delete; if uvc_v4l2_open() runs after the state is set, it will run before uvc_delete(), see the state, and return immediately -- uvc_delete() does uvc_unregister_video() (and hence video_unregister_device(), which is synchronized with videodev_lock) as its first thing, so there is no risk of use-after-free in uvc_v4l2_open(). Bug diagnosed based on a lockdep warning reported by Romano Giannetti <[EMAIL PROTECTED]>. Signed-off-by: Roland Dreier <[EMAIL PROTECTED]> Signed-off-by: Laurent Pinchart <[EMAIL PROTECTED]> Signed-off-by: Mauro Carvalho Chehab <[EMAIL PROTECTED]> --- linux/drivers/media/video/uvc/uvc_driver.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff -r 73bf7e40d26f -r 2e0eac009f3c linux/drivers/media/video/uvc/uvc_driver.c --- a/linux/drivers/media/video/uvc/uvc_driver.c Fri Jul 04 06:33:23 2008 +0000 +++ b/linux/drivers/media/video/uvc/uvc_driver.c Fri Jul 11 19:32:15 2008 +0000 @@ -1633,13 +1633,16 @@ static void uvc_disconnect(struct usb_in * reference to the uvc_device instance after uvc_v4l2_open() received * the pointer to the device (video_devdata) but before it got the * chance to increase the reference count (kref_get). + * + * Note that the reference can't be released with the lock held, + * otherwise a AB-BA deadlock can occur with videodev_lock that + * videodev acquires in videodev_open() and video_unregister_device(). */ mutex_lock(&uvc_driver.open_mutex); - dev->state |= UVC_DEV_DISCONNECTED; + mutex_unlock(&uvc_driver.open_mutex); + kref_put(&dev->kref, uvc_delete); - - mutex_unlock(&uvc_driver.open_mutex); } static int uvc_suspend(struct usb_interface *intf, pm_message_t message) --- Patch is available at: http://linuxtv.org/hg/v4l-dvb/rev/2e0eac009f3c4945741f2d1a3bc2838b8b917c89 _______________________________________________ linuxtv-commits mailing list linuxtv-commits@linuxtv.org http://www.linuxtv.org/cgi-bin/mailman/listinfo/linuxtv-commits