diff options
author | Al Viro <viro@ZenIV.linux.org.uk> | 2013-05-09 22:03:33 +0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2013-05-21 15:56:56 +0400 |
commit | a242f426108c284049a69710f871cc9f11b13e61 (patch) | |
tree | 0cddab2680085f478cf5c5c5b168143de90e8b30 /drivers/media/v4l2-core/videobuf-vmalloc.c | |
parent | 0735647c29bca5f33f38fcf457b3b0e9e5912f51 (diff) | |
download | linux-a242f426108c284049a69710f871cc9f11b13e61.tar.xz |
[media] videobuf_vm_{open,close} race fixes
just use videobuf_queue_lock(map->q) to protect map->count; vm_area_operations
->open() and ->close() are called just under vma->vm_mm->mmap_sem, which
doesn't help the drivers at all, since clonal VMAs are normally in different
address spaces...
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/v4l2-core/videobuf-vmalloc.c')
-rw-r--r-- | drivers/media/v4l2-core/videobuf-vmalloc.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/drivers/media/v4l2-core/videobuf-vmalloc.c b/drivers/media/v4l2-core/videobuf-vmalloc.c index 2ff7fcc77b11..1365c651c177 100644 --- a/drivers/media/v4l2-core/videobuf-vmalloc.c +++ b/drivers/media/v4l2-core/videobuf-vmalloc.c @@ -54,11 +54,14 @@ MODULE_LICENSE("GPL"); static void videobuf_vm_open(struct vm_area_struct *vma) { struct videobuf_mapping *map = vma->vm_private_data; + struct videobuf_queue *q = map->q; dprintk(2, "vm_open %p [count=%u,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); + videobuf_queue_lock(q); map->count++; + videobuf_queue_unlock(q); } static void videobuf_vm_close(struct vm_area_struct *vma) @@ -70,12 +73,11 @@ static void videobuf_vm_close(struct vm_area_struct *vma) dprintk(2, "vm_close %p [count=%u,vma=%08lx-%08lx]\n", map, map->count, vma->vm_start, vma->vm_end); - map->count--; - if (0 == map->count) { + videobuf_queue_lock(q); + if (!--map->count) { struct videobuf_vmalloc_memory *mem; dprintk(1, "munmap %p q=%p\n", map, q); - videobuf_queue_lock(q); /* We need first to cancel streams, before unmapping */ if (q->streaming) @@ -114,8 +116,8 @@ static void videobuf_vm_close(struct vm_area_struct *vma) kfree(map); - videobuf_queue_unlock(q); } + videobuf_queue_unlock(q); return; } |