aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2010-12-30 17:54:33 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-01-19 08:44:54 -0500
commit27074efa2ee8c1ef07dc5f644104e35d39e43322 (patch)
tree2ba18e26633ad557b37cc3b42c1cd1381c069d61
parent4e770f7602fb2285f3106f98109d0685618ddc22 (diff)
[media] gspca_main: Locking fixes 2
Before this patch vidioc_dqbuf is using its own read_lock, where as other queue related functions use queue_lock. This means that dqbuf is accessing several variables in a racy manor. The most important one being fr_o, which may be changed from underneath dqbuf by vidioc_reqbufs or vidioc_streamoff. Other variables which it accesses unprotected are gspca_dev->memory, gspca_dev->streaming and gspca_dev->capt_file. This patch fixes this by changing vidioc_dqbuf to also use the queue_lock. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Acked-by: Jean-Francois Moine <moinejf@free.fr> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/gspca/gspca.c112
-rw-r--r--drivers/media/video/gspca/gspca.h1
2 files changed, 58 insertions, 55 deletions
diff --git a/drivers/media/video/gspca/gspca.c b/drivers/media/video/gspca/gspca.c
index 74626b6a9eb4..64ecf669d655 100644
--- a/drivers/media/video/gspca/gspca.c
+++ b/drivers/media/video/gspca/gspca.c
@@ -1831,33 +1831,77 @@ out:
1831 return ret; 1831 return ret;
1832} 1832}
1833 1833
1834static int frame_ready_nolock(struct gspca_dev *gspca_dev, struct file *file,
1835 enum v4l2_memory memory)
1836{
1837 if (!gspca_dev->present)
1838 return -ENODEV;
1839 if (gspca_dev->capt_file != file || gspca_dev->memory != memory ||
1840 !gspca_dev->streaming)
1841 return -EINVAL;
1842
1843 /* check if a frame is ready */
1844 return gspca_dev->fr_o != atomic_read(&gspca_dev->fr_i);
1845}
1846
1847static int frame_ready(struct gspca_dev *gspca_dev, struct file *file,
1848 enum v4l2_memory memory)
1849{
1850 int ret;
1851
1852 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1853 return -ERESTARTSYS;
1854 ret = frame_ready_nolock(gspca_dev, file, memory);
1855 mutex_unlock(&gspca_dev->queue_lock);
1856 return ret;
1857}
1858
1834/* 1859/*
1835 * wait for a video frame 1860 * dequeue a video buffer
1836 * 1861 *
1837 * If a frame is ready, its index is returned. 1862 * If nonblock_ing is false, block until a buffer is available.
1838 */ 1863 */
1839static int frame_wait(struct gspca_dev *gspca_dev, 1864static int vidioc_dqbuf(struct file *file, void *priv,
1840 int nonblock_ing) 1865 struct v4l2_buffer *v4l2_buf)
1841{ 1866{
1842 int i, ret; 1867 struct gspca_dev *gspca_dev = priv;
1868 struct gspca_frame *frame;
1869 int i, j, ret;
1843 1870
1844 /* check if a frame is ready */ 1871 PDEBUG(D_FRAM, "dqbuf");
1845 i = gspca_dev->fr_o; 1872
1846 if (i == atomic_read(&gspca_dev->fr_i)) { 1873 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1847 if (nonblock_ing) 1874 return -ERESTARTSYS;
1875
1876 for (;;) {
1877 ret = frame_ready_nolock(gspca_dev, file, v4l2_buf->memory);
1878 if (ret < 0)
1879 goto out;
1880 if (ret > 0)
1881 break;
1882
1883 mutex_unlock(&gspca_dev->queue_lock);
1884
1885 if (file->f_flags & O_NONBLOCK)
1848 return -EAGAIN; 1886 return -EAGAIN;
1849 1887
1850 /* wait till a frame is ready */ 1888 /* wait till a frame is ready */
1851 ret = wait_event_interruptible_timeout(gspca_dev->wq, 1889 ret = wait_event_interruptible_timeout(gspca_dev->wq,
1852 i != atomic_read(&gspca_dev->fr_i) || 1890 frame_ready(gspca_dev, file, v4l2_buf->memory),
1853 !gspca_dev->streaming || !gspca_dev->present,
1854 msecs_to_jiffies(3000)); 1891 msecs_to_jiffies(3000));
1855 if (ret < 0) 1892 if (ret < 0)
1856 return ret; 1893 return ret;
1857 if (ret == 0 || !gspca_dev->streaming || !gspca_dev->present) 1894 if (ret == 0)
1858 return -EIO; 1895 return -EIO;
1896
1897 if (mutex_lock_interruptible(&gspca_dev->queue_lock))
1898 return -ERESTARTSYS;
1859 } 1899 }
1860 1900
1901 i = gspca_dev->fr_o;
1902 j = gspca_dev->fr_queue[i];
1903 frame = &gspca_dev->frame[j];
1904
1861 gspca_dev->fr_o = (i + 1) % GSPCA_MAX_FRAMES; 1905 gspca_dev->fr_o = (i + 1) % GSPCA_MAX_FRAMES;
1862 1906
1863 if (gspca_dev->sd_desc->dq_callback) { 1907 if (gspca_dev->sd_desc->dq_callback) {
@@ -1867,46 +1911,7 @@ static int frame_wait(struct gspca_dev *gspca_dev,
1867 gspca_dev->sd_desc->dq_callback(gspca_dev); 1911 gspca_dev->sd_desc->dq_callback(gspca_dev);
1868 mutex_unlock(&gspca_dev->usb_lock); 1912 mutex_unlock(&gspca_dev->usb_lock);
1869 } 1913 }
1870 return gspca_dev->fr_queue[i];
1871}
1872
1873/*
1874 * dequeue a video buffer
1875 *
1876 * If nonblock_ing is false, block until a buffer is available.
1877 */
1878static int vidioc_dqbuf(struct file *file, void *priv,
1879 struct v4l2_buffer *v4l2_buf)
1880{
1881 struct gspca_dev *gspca_dev = priv;
1882 struct gspca_frame *frame;
1883 int i, ret;
1884
1885 PDEBUG(D_FRAM, "dqbuf");
1886 if (v4l2_buf->memory != gspca_dev->memory)
1887 return -EINVAL;
1888 1914
1889 if (!gspca_dev->present)
1890 return -ENODEV;
1891
1892 /* if not streaming, be sure the application will not loop forever */
1893 if (!(file->f_flags & O_NONBLOCK)
1894 && !gspca_dev->streaming && gspca_dev->users == 1)
1895 return -EINVAL;
1896
1897 /* only the capturing file may dequeue */
1898 if (gspca_dev->capt_file != file)
1899 return -EINVAL;
1900
1901 /* only one dequeue / read at a time */
1902 if (mutex_lock_interruptible(&gspca_dev->read_lock))
1903 return -ERESTARTSYS;
1904
1905 ret = frame_wait(gspca_dev, file->f_flags & O_NONBLOCK);
1906 if (ret < 0)
1907 goto out;
1908 i = ret; /* frame index */
1909 frame = &gspca_dev->frame[i];
1910 if (gspca_dev->memory == V4L2_MEMORY_USERPTR) { 1915 if (gspca_dev->memory == V4L2_MEMORY_USERPTR) {
1911 if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr, 1916 if (copy_to_user((__u8 __user *) frame->v4l2_buf.m.userptr,
1912 frame->data, 1917 frame->data,
@@ -1919,10 +1924,10 @@ static int vidioc_dqbuf(struct file *file, void *priv,
1919 } 1924 }
1920 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE; 1925 frame->v4l2_buf.flags &= ~V4L2_BUF_FLAG_DONE;
1921 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf); 1926 memcpy(v4l2_buf, &frame->v4l2_buf, sizeof *v4l2_buf);
1922 PDEBUG(D_FRAM, "dqbuf %d", i); 1927 PDEBUG(D_FRAM, "dqbuf %d", j);
1923 ret = 0; 1928 ret = 0;
1924out: 1929out:
1925 mutex_unlock(&gspca_dev->read_lock); 1930 mutex_unlock(&gspca_dev->queue_lock);
1926 return ret; 1931 return ret;
1927} 1932}
1928 1933
@@ -2270,7 +2275,6 @@ int gspca_dev_probe2(struct usb_interface *intf,
2270 goto out; 2275 goto out;
2271 2276
2272 mutex_init(&gspca_dev->usb_lock); 2277 mutex_init(&gspca_dev->usb_lock);
2273 mutex_init(&gspca_dev->read_lock);
2274 mutex_init(&gspca_dev->queue_lock); 2278 mutex_init(&gspca_dev->queue_lock);
2275 init_waitqueue_head(&gspca_dev->wq); 2279 init_waitqueue_head(&gspca_dev->wq);
2276 2280
diff --git a/drivers/media/video/gspca/gspca.h b/drivers/media/video/gspca/gspca.h
index 97b77a26a2eb..a2a1a6aa0606 100644
--- a/drivers/media/video/gspca/gspca.h
+++ b/drivers/media/video/gspca/gspca.h
@@ -205,7 +205,6 @@ struct gspca_dev {
205 205
206 wait_queue_head_t wq; /* wait queue */ 206 wait_queue_head_t wq; /* wait queue */
207 struct mutex usb_lock; /* usb exchange protection */ 207 struct mutex usb_lock; /* usb exchange protection */
208 struct mutex read_lock; /* read protection */
209 struct mutex queue_lock; /* ISOC queue protection */ 208 struct mutex queue_lock; /* ISOC queue protection */
210 int usb_err; /* USB error - protected by usb_lock */ 209 int usb_err; /* USB error - protected by usb_lock */
211 u16 pkt_size; /* ISOC packet size */ 210 u16 pkt_size; /* ISOC packet size */