mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-24 01:41:39 +00:00
[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>
This commit is contained in:
parent
0735647c29
commit
a242f42610
3 changed files with 19 additions and 13 deletions
|
@ -66,11 +66,14 @@ static void __videobuf_dc_free(struct device *dev,
|
|||
static void videobuf_vm_open(struct vm_area_struct *vma)
|
||||
{
|
||||
struct videobuf_mapping *map = vma->vm_private_data;
|
||||
struct videobuf_queue *q = map->q;
|
||||
|
||||
dev_dbg(map->q->dev, "vm_open %p [count=%u,vma=%08lx-%08lx]\n",
|
||||
dev_dbg(q->dev, "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)
|
||||
|
@ -82,12 +85,11 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
|
|||
dev_dbg(q->dev, "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_dma_contig_memory *mem;
|
||||
|
||||
dev_dbg(q->dev, "munmap %p q=%p\n", map, q);
|
||||
videobuf_queue_lock(q);
|
||||
|
||||
/* We need first to cancel streams, before unmapping */
|
||||
if (q->streaming)
|
||||
|
@ -126,8 +128,8 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
|
|||
|
||||
kfree(map);
|
||||
|
||||
videobuf_queue_unlock(q);
|
||||
}
|
||||
videobuf_queue_unlock(q);
|
||||
}
|
||||
|
||||
static const struct vm_operations_struct videobuf_vm_ops = {
|
||||
|
|
|
@ -338,11 +338,14 @@ EXPORT_SYMBOL_GPL(videobuf_dma_free);
|
|||
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=%d,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)
|
||||
|
@ -355,10 +358,9 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
|
|||
dprintk(2, "vm_close %p [count=%d,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) {
|
||||
dprintk(1, "munmap %p q=%p\n", map, q);
|
||||
videobuf_queue_lock(q);
|
||||
for (i = 0; i < VIDEO_MAX_FRAME; i++) {
|
||||
if (NULL == q->bufs[i])
|
||||
continue;
|
||||
|
@ -374,9 +376,9 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
|
|||
q->bufs[i]->baddr = 0;
|
||||
q->ops->buf_release(q, q->bufs[i]);
|
||||
}
|
||||
videobuf_queue_unlock(q);
|
||||
kfree(map);
|
||||
}
|
||||
videobuf_queue_unlock(q);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue