From: Al Viro Date: Thu, 23 May 2013 08:38:22 +0000 (-0400) Subject: zoran: racy refcount handling in vm_ops ->open()/->close() X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=4ad1f70ebcdb69393ce083f514bf4a4a3a3e65cb;p=GitHub%2Fmoto-9609%2Fandroid_kernel_motorola_exynos9610.git 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 --- 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; struct zoran_mapping { struct zoran_fh *fh; - int count; + atomic_t count; }; struct 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 zoran_vm_open (struct vm_area_struct *vma) { struct zoran_mapping *map = vma->vm_private_data; - - map->count++; + atomic_inc(&map->count); } static void @@ -2815,7 +2814,7 @@ zoran_vm_close (struct vm_area_struct *vma) struct zoran *zr = fh->zr; int i; - if (--map->count > 0) + if (!atomic_dec_and_mutex_lock(&map->count, &zr->resource_lock)) return; 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); /* Any buffers still mapped? */ - for (i = 0; i < fh->buffers.num_buffers; i++) - if (fh->buffers.buffer[i].map) + for (i = 0; i < fh->buffers.num_buffers; i++) { + if (fh->buffers.buffer[i].map) { + mutex_unlock(&zr->resource_lock); return; + } + } dprintk(3, KERN_INFO "%s: %s - free %s buffers\n", ZR_DEVNAME(zr), __func__, mode_name(fh->map_mode)); - mutex_lock(&zr->resource_lock); if (fh->map_mode == ZORAN_MAP_MODE_RAW) { if (fh->buffers.active != ZORAN_FREE) { @@ -2939,7 +2940,7 @@ zoran_mmap (struct file *file, goto mmap_unlock_and_return; } map->fh = fh; - map->count = 1; + atomic_set(&map->count, 1); vma->vm_ops = &zoran_vm_ops; vma->vm_flags |= VM_DONTEXPAND;