diff options
author | Marek Szyprowski <m.szyprowski@samsung.com> | 2011-11-17 09:32:17 +0100 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-12-30 19:06:49 +0100 |
commit | b037c0fde22b1d3cd0b3c3717d28e54619fc1592 (patch) | |
tree | 92d4c05c8e3f777c288546d5592cdf8ce4b70a89 /drivers/media/video/videobuf2-dma-sg.c | |
parent | [media] media: vb2: fix queueing of userptr buffers with null buffer pointer (diff) | |
download | linux-b037c0fde22b1d3cd0b3c3717d28e54619fc1592.tar.xz linux-b037c0fde22b1d3cd0b3c3717d28e54619fc1592.zip |
[media] media: vb2: fix potential deadlock in mmap vs. get_userptr handling
To get direct access to userspace memory pages vb2 allocator needs to
gather read access on mmap semaphore in the current process.
The same semaphore is taken before calling mmap operation, while
both mmap and qbuf are called by the driver or v4l2 core with
driver's lock held. To avoid a AB-BA deadlock (mmap_sem then
driver's lock in mmap and driver's lock then mmap_sem in qbuf)
the videobuf2 core release driver's lock, takes mmap_sem and then
takes again driver's lock. get_userptr methods are now called with
all needed locks already taken to avoid further lock magic inside
memory allocator's code.
Reported-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
CC: Pawel Osciak <pawel@osciak.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/videobuf2-dma-sg.c')
-rw-r--r-- | drivers/media/video/videobuf2-dma-sg.c | 3 |
1 files changed, 1 insertions, 2 deletions
diff --git a/drivers/media/video/videobuf2-dma-sg.c b/drivers/media/video/videobuf2-dma-sg.c index 3bad8b105fea..25c3b360e1ad 100644 --- a/drivers/media/video/videobuf2-dma-sg.c +++ b/drivers/media/video/videobuf2-dma-sg.c @@ -140,7 +140,6 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr, if (!buf->pages) goto userptr_fail_pages_array_alloc; - down_read(¤t->mm->mmap_sem); num_pages_from_user = get_user_pages(current, current->mm, vaddr & PAGE_MASK, buf->sg_desc.num_pages, @@ -148,7 +147,7 @@ static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr, 1, /* force */ buf->pages, NULL); - up_read(¤t->mm->mmap_sem); + if (num_pages_from_user != buf->sg_desc.num_pages) goto userptr_fail_get_user_pages; |