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>
This commit is contained in:
Al Viro 2013-05-23 04:38:22 -04:00
parent 448293aadb
commit 4ad1f70ebc
2 changed files with 9 additions and 8 deletions

View File

@ -176,7 +176,7 @@ struct zoran_fh;
struct zoran_mapping { struct zoran_mapping {
struct zoran_fh *fh; struct zoran_fh *fh;
int count; atomic_t count;
}; };
struct zoran_buffer { struct zoran_buffer {

View File

@ -2803,8 +2803,7 @@ static void
zoran_vm_open (struct vm_area_struct *vma) zoran_vm_open (struct vm_area_struct *vma)
{ {
struct zoran_mapping *map = vma->vm_private_data; struct zoran_mapping *map = vma->vm_private_data;
atomic_inc(&map->count);
map->count++;
} }
static void static void
@ -2815,7 +2814,7 @@ zoran_vm_close (struct vm_area_struct *vma)
struct zoran *zr = fh->zr; struct zoran *zr = fh->zr;
int i; int i;
if (--map->count > 0) if (!atomic_dec_and_mutex_lock(&map->count, &zr->resource_lock))
return; return;
dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr), dprintk(3, KERN_INFO "%s: %s - munmap(%s)\n", ZR_DEVNAME(zr),
@ -2828,14 +2827,16 @@ zoran_vm_close (struct vm_area_struct *vma)
kfree(map); kfree(map);
/* Any buffers still mapped? */ /* Any buffers still mapped? */
for (i = 0; i < fh->buffers.num_buffers; i++) for (i = 0; i < fh->buffers.num_buffers; i++) {
if (fh->buffers.buffer[i].map) if (fh->buffers.buffer[i].map) {
mutex_unlock(&zr->resource_lock);
return; return;
}
}
dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr), dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr),
__func__, mode_name(fh->map_mode)); __func__, mode_name(fh->map_mode));
mutex_lock(&zr->resource_lock);
if (fh->map_mode == ZORAN_MAP_MODE_RAW) { if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
if (fh->buffers.active != ZORAN_FREE) { if (fh->buffers.active != ZORAN_FREE) {
@ -2939,7 +2940,7 @@ zoran_mmap (struct file *file,
goto mmap_unlock_and_return; goto mmap_unlock_and_return;
} }
map->fh = fh; map->fh = fh;
map->count = 1; atomic_set(&map->count, 1);
vma->vm_ops = &zoran_vm_ops; vma->vm_ops = &zoran_vm_ops;
vma->vm_flags |= VM_DONTEXPAND; vma->vm_flags |= VM_DONTEXPAND;