aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorJonathan Gonzalez V <zeus@gnu.org>2014-06-04 19:07:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-04 19:54:00 -0400
commitcbe97414c24b3ceb9b8df9e45b798a88daae7f71 (patch)
tree801a090e9ad5b69fb6a12e9e5268fa836b80fa43 /drivers/gpu
parent5040573e49cc8f0e016a83544a0e552f2f44c897 (diff)
drm/exynos: call find_vma with the mmap_sem held
Performing vma lookups without taking the mm->mmap_sem is asking for trouble. While doing the search, the vma in question can be modified or even removed before returning to the caller. Take the lock (exclusively) in order to avoid races while iterating through the vmacache and/or rbtree. Signed-off-by: Jonathan Gonzalez V <zeus@gnu.org> Signed-off-by: Davidlohr Bueso <davidlohr@hp.com> Cc: Inki Dae <inki.dae@samsung.com> Cc: Joonyoung Shim <jy0922.shim@samsung.com> Cc: David Airlie <airlied@linux.ie> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 6c1885eedfdf..800158714473 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -467,14 +467,17 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
467 goto err_free; 467 goto err_free;
468 } 468 }
469 469
470 down_read(&current->mm->mmap_sem);
470 vma = find_vma(current->mm, userptr); 471 vma = find_vma(current->mm, userptr);
471 if (!vma) { 472 if (!vma) {
473 up_read(&current->mm->mmap_sem);
472 DRM_ERROR("failed to get vm region.\n"); 474 DRM_ERROR("failed to get vm region.\n");
473 ret = -EFAULT; 475 ret = -EFAULT;
474 goto err_free_pages; 476 goto err_free_pages;
475 } 477 }
476 478
477 if (vma->vm_end < userptr + size) { 479 if (vma->vm_end < userptr + size) {
480 up_read(&current->mm->mmap_sem);
478 DRM_ERROR("vma is too small.\n"); 481 DRM_ERROR("vma is too small.\n");
479 ret = -EFAULT; 482 ret = -EFAULT;
480 goto err_free_pages; 483 goto err_free_pages;
@@ -482,6 +485,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
482 485
483 g2d_userptr->vma = exynos_gem_get_vma(vma); 486 g2d_userptr->vma = exynos_gem_get_vma(vma);
484 if (!g2d_userptr->vma) { 487 if (!g2d_userptr->vma) {
488 up_read(&current->mm->mmap_sem);
485 DRM_ERROR("failed to copy vma.\n"); 489 DRM_ERROR("failed to copy vma.\n");
486 ret = -ENOMEM; 490 ret = -ENOMEM;
487 goto err_free_pages; 491 goto err_free_pages;
@@ -492,10 +496,12 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
492 ret = exynos_gem_get_pages_from_userptr(start & PAGE_MASK, 496 ret = exynos_gem_get_pages_from_userptr(start & PAGE_MASK,
493 npages, pages, vma); 497 npages, pages, vma);
494 if (ret < 0) { 498 if (ret < 0) {
499 up_read(&current->mm->mmap_sem);
495 DRM_ERROR("failed to get user pages from userptr.\n"); 500 DRM_ERROR("failed to get user pages from userptr.\n");
496 goto err_put_vma; 501 goto err_put_vma;
497 } 502 }
498 503
504 up_read(&current->mm->mmap_sem);
499 g2d_userptr->pages = pages; 505 g2d_userptr->pages = pages;
500 506
501 sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); 507 sgt = kzalloc(sizeof(*sgt), GFP_KERNEL);