[PATCH] drm/exynos: fix deadlock issue at mmap

Inki Dae inki.dae at samsung.com
Mon Sep 23 03:42:31 PDT 2013


This patch fixes the deadlock issue when another process requested
mmap system call.

This issue can incur the deadlock if another process sharing the same
file called mmap system call between ->f_op pointer chaning and restoring.

So this patch calls down_write(&mm->mmap_sem) before do_mmap_pgoff
call and then up_write(&mm->mmap_sem) after do_mmap_pg_off call
so that when another process called mmap system call, the process
can wait for up_write() call until the ->f_op pointer is restored.

Signed-off-by: Inki Dae <inki.dae at samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
 drivers/gpu/drm/exynos/exynos_drm_gem.c |   20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 49f9cd2..779c2d7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -13,6 +13,7 @@
 #include <drm/drm_vma_manager.h>
 
 #include <linux/shmem_fs.h>
+#include <linux/security.h>
 #include <drm/exynos_drm.h>
 
 #include "exynos_drm_drv.h"
@@ -420,6 +421,7 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
 {
 	struct drm_exynos_gem_mmap *args = data;
 	struct drm_gem_object *obj;
+	struct mm_struct *mm = current->mm;
 	unsigned long addr;
 
 	if (!(dev->driver->driver_features & DRIVER_GEM)) {
@@ -433,6 +435,8 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
 		return -EINVAL;
 	}
 
+	down_write(&mm->mmap_sem);
+
 	/*
 	 * We have to use gem object and its fops for specific mmaper,
 	 * but vm_mmap() can deliver only filp. So we have to change
@@ -457,8 +461,17 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
 	 */
 	file_priv->filp->private_data = obj;
 
-	addr = vm_mmap(file_priv->filp, 0, args->size,
-			PROT_READ | PROT_WRITE, MAP_SHARED, 0);
+	addr = security_mmap_file(file_priv->filp, PROT_READ | PROT_WRITE,
+					MAP_SHARED);
+	if (!addr) {
+		unsigned long populate;
+
+		addr = do_mmap_pgoff(file_priv->filp, 0, args->size,
+					PROT_READ | PROT_WRITE,
+					MAP_SHARED, 0, &populate);
+		if (populate)
+			mm_populate(addr, populate);
+	}
 
 	drm_gem_object_unreference(obj);
 
@@ -469,10 +482,13 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
 			file_priv->filp->private_data = file_priv;
 		}
 		mutex_unlock(&dev->struct_mutex);
+		up_write(&mm->mmap_sem);
+
 		return (int)addr;
 	}
 
 	mutex_unlock(&dev->struct_mutex);
+	up_write(&mm->mmap_sem);
 
 	args->mapped = addr;
 
-- 
1.7.9.5



More information about the dri-devel mailing list