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

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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@xxxxxxxxxxx>
Signed-off-by: Kyungmin Park <kyungmin.park@xxxxxxxxxxx>
---
 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

_______________________________________________
dri-devel mailing list
dri-devel@xxxxxxxxxxxxxxxxxxxxx
http://lists.freedesktop.org/mailman/listinfo/dri-devel




[Index of Archives]     [Linux DRI Users]     [Linux Intel Graphics]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [XFree86]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux