summaryrefslogtreecommitdiffstats
path: root/drivers/media/video/videobuf2-dma-sg.c
diff options
context:
space:
mode:
authorMarek Szyprowski <m.szyprowski@samsung.com>2011-11-17 05:32:17 -0300
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-12-30 16:06:49 -0200
commitb037c0fde22b1d3cd0b3c3717d28e54619fc1592 (patch)
tree92d4c05c8e3f777c288546d5592cdf8ce4b70a89 /drivers/media/video/videobuf2-dma-sg.c
parentf0b7c7fc6f15e823cb4a5d225d9ef28b884ab6ec (diff)
[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.c3
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 3bad8b105fe..25c3b360e1a 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(&current->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(&current->mm->mmap_sem);
+
if (num_pages_from_user != buf->sg_desc.num_pages)
goto userptr_fail_get_user_pages;