From af6f5064170ebb6472c9d21928b58d324ae9e544 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 25 Mar 2004 00:53:25 -0800 Subject: [PATCH] [PATCH] USB: race condition in open of w9968cf there's a race in how open handles multiple openers. You implement exclusive opening and wait for close in case of further openers. However if there are more than one waiter, only one of them must be allowed to proceed. --- drivers/usb/media/w9968cf.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c index 4dd52530b2d62..b69de96c6196d 100644 --- a/drivers/usb/media/w9968cf.c +++ b/drivers/usb/media/w9968cf.c @@ -905,8 +905,7 @@ static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs) spin_unlock(&cam->urb_lock); /* Wake up the user process */ - if (waitqueue_active(&cam->wait_queue)) - wake_up_interruptible(&cam->wait_queue); + wake_up_interruptible(&cam->wait_queue); } @@ -2690,6 +2689,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp) up(&cam->dev_sem); return -EWOULDBLOCK; } +retry: up(&cam->dev_sem); err = wait_event_interruptible(cam->open, cam->disconnected || (cam->users == 0)); @@ -2698,6 +2698,9 @@ static int w9968cf_open(struct inode* inode, struct file* filp) if (cam->disconnected) return -ENODEV; down(&cam->dev_sem); + /*recheck - there may be several waiters */ + if (cam->users) + goto retry; } DBG(5, "Opening '%s', /dev/video%d ...", @@ -2758,8 +2761,7 @@ static int w9968cf_release(struct inode* inode, struct file* filp) cam->users--; w9968cf_deallocate_memory(cam); - if (waitqueue_active(&cam->open)) - wake_up_interruptible(&cam->open); + wake_up_interruptible(&cam->open); DBG(5, "Video device closed.") up(&cam->dev_sem); -- 2.53.0