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

Reply via email to