Commit af6f5064 authored by Oliver Neukum's avatar Oliver Neukum Committed by Greg Kroah-Hartman

[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.
parent c107b960
...@@ -905,8 +905,7 @@ static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs) ...@@ -905,8 +905,7 @@ static void w9968cf_urb_complete(struct urb *urb, struct pt_regs *regs)
spin_unlock(&cam->urb_lock); spin_unlock(&cam->urb_lock);
/* Wake up the user process */ /* 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) ...@@ -2690,6 +2689,7 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
up(&cam->dev_sem); up(&cam->dev_sem);
return -EWOULDBLOCK; return -EWOULDBLOCK;
} }
retry:
up(&cam->dev_sem); up(&cam->dev_sem);
err = wait_event_interruptible(cam->open, cam->disconnected || err = wait_event_interruptible(cam->open, cam->disconnected ||
(cam->users == 0)); (cam->users == 0));
...@@ -2698,6 +2698,9 @@ static int w9968cf_open(struct inode* inode, struct file* filp) ...@@ -2698,6 +2698,9 @@ static int w9968cf_open(struct inode* inode, struct file* filp)
if (cam->disconnected) if (cam->disconnected)
return -ENODEV; return -ENODEV;
down(&cam->dev_sem); down(&cam->dev_sem);
/*recheck - there may be several waiters */
if (cam->users)
goto retry;
} }
DBG(5, "Opening '%s', /dev/video%d ...", DBG(5, "Opening '%s', /dev/video%d ...",
...@@ -2758,8 +2761,7 @@ static int w9968cf_release(struct inode* inode, struct file* filp) ...@@ -2758,8 +2761,7 @@ static int w9968cf_release(struct inode* inode, struct file* filp)
cam->users--; cam->users--;
w9968cf_deallocate_memory(cam); w9968cf_deallocate_memory(cam);
if (waitqueue_active(&cam->open)) wake_up_interruptible(&cam->open);
wake_up_interruptible(&cam->open);
DBG(5, "Video device closed.") DBG(5, "Video device closed.")
up(&cam->dev_sem); up(&cam->dev_sem);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment