aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2013-05-23 04:38:22 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2013-05-31 15:33:32 -0400
commit4ad1f70ebcdb69393ce083f514bf4a4a3a3e65cb (patch)
tree686f96672a8432dffe178a155891e1806e083713 /drivers/media
parent448293aadb54ab38b9c053bf9f1eecafdc0ed214 (diff)
zoran: racy refcount handling in vm_ops ->open()/->close()
worse, we lock ->resource_lock too late when we are destroying the final clonal VMA; the check for lack of other mappings of the same opened file can race with mmap(). Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/pci/zoran/zoran.h2
-rw-r--r--drivers/media/pci/zoran/zoran_driver.c15
2 files changed, 9 insertions, 8 deletions
diff --git a/drivers/media/pci/zoran/zoran.h b/drivers/media/pci/zoran/zoran.h
index ca2754a3cd63..5e040085c2ff 100644
--- a/drivers/media/pci/zoran/zoran.h
+++ b/drivers/media/pci/zoran/zoran.h
@@ -176,7 +176,7 @@ struct zoran_fh;
176 176
177struct zoran_mapping { 177struct zoran_mapping {
178 struct zoran_fh *fh; 178 struct zoran_fh *fh;
179 int count; 179 atomic_t count;
180}; 180};
181 181
182struct zoran_buffer { 182struct zoran_buffer {
diff --git a/drivers/media/pci/zoran/zoran_driver.c b/drivers/media/pci/zoran/zoran_driver.c
index 1168a84a737d..d133c30c3fdc 100644
--- a/drivers/media/pci/zoran/zoran_driver.c
+++ b/drivers/media/pci/zoran/zoran_driver.c
@@ -2803,8 +2803,7 @@ static void
2803zoran_vm_open (struct vm_area_struct *vma) 2803zoran_vm_open (struct vm_area_struct *vma)
2804{ 2804{
2805 struct zoran_mapping *map = vma->vm_private_data; 2805 struct zoran_mapping *map = vma->vm_private_data;
2806 2806 atomic_inc(&map->count);
2807 map->count++;
2808} 2807}
2809 2808
2810static void 2809static void
@@ -2815,7 +2814,7 @@ zoran_vm_close (struct vm_area_struct *vma)
2815 struct zoran *zr = fh->zr; 2814 struct zoran *zr = fh->zr;
2816 int i; 2815 int i;
2817 2816
2818 if (--map->count > 0) 2817 if (!atomic_dec_and_mutex_lock(&map->count, &zr->resource_lock))
2819 return; 2818 return;
2820 2819
2821 dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr), 2820 dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr),
@@ -2828,14 +2827,16 @@ zoran_vm_close (struct vm_area_struct *vma)
2828 kfree(map); 2827 kfree(map);
2829 2828
2830 /* Any buffers still mapped? */ 2829 /* Any buffers still mapped? */
2831 for (i = 0; i < fh->buffers.num_buffers; i++) 2830 for (i = 0; i < fh->buffers.num_buffers; i++) {
2832 if (fh->buffers.buffer[i].map) 2831 if (fh->buffers.buffer[i].map) {
2832 mutex_unlock(&zr->resource_lock);
2833 return; 2833 return;
2834 }
2835 }
2834 2836
2835 dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr), 2837 dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr),
2836 __func__, mode_name(fh->map_mode)); 2838 __func__, mode_name(fh->map_mode));
2837 2839
2838 mutex_lock(&zr->resource_lock);
2839 2840
2840 if (fh->map_mode == ZORAN_MAP_MODE_RAW) { 2841 if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
2841 if (fh->buffers.active != ZORAN_FREE) { 2842 if (fh->buffers.active != ZORAN_FREE) {
@@ -2939,7 +2940,7 @@ zoran_mmap (struct file *file,
2939 goto mmap_unlock_and_return; 2940 goto mmap_unlock_and_return;
2940 } 2941 }
2941 map->fh = fh; 2942 map->fh = fh;
2942 map->count = 1; 2943 atomic_set(&map->count, 1);
2943 2944
2944 vma->vm_ops = &zoran_vm_ops; 2945 vma->vm_ops = &zoran_vm_ops;
2945 vma->vm_flags |= VM_DONTEXPAND; 2946 vma->vm_flags |= VM_DONTEXPAND;