drm/prime: resolve race for drm_gem_prime_handle_to_fd() 40/55140/1
authorYoungJun Cho <yj44.cho@samsung.com>
Tue, 4 Feb 2014 07:24:35 +0000 (16:24 +0900)
committerJoonyoung Shim <jy0922.shim@samsung.com>
Tue, 22 Dec 2015 07:34:07 +0000 (16:34 +0900)
This patch resolves race for drm_gem_prime_handle_to_fd().
There could be a race when drm_gem_prime_handle_to_fd() is
requested during __fput() is executed with same dmabuf.

Change-Id: I8ab68a7184ce974ded84c75a7805b9aa1d021ee2
Signed-off-by: YoungJun Cho <yj44.cho@samsung.com>
Signed-off-by: Rohit kumar <rohit.kr@samsung.com>
drivers/gpu/drm/drm_prime.c
include/drm/drmP.h

index 0d71f81..83cc31c 100644 (file)
@@ -63,6 +63,28 @@ struct drm_prime_member {
        uint32_t handle;
 };
 
+bool drm_prime_check_dmabuf_valid(struct dma_buf *dmabuf)
+{
+       struct file *file = dmabuf->file;
+
+       /*
+        * There could be a race when drm_gem_prime_handle_to_fd() is requested
+        * during __fput() is executed with same dmabuf.
+        * Let's suppose that there are process A and B. A creates a gem obj
+        * and exports it to dmabuf, B opens gem name which comes from A.
+        * And A is closing dmabuf and B tries to import dmabuf at that time.
+        * In this case, the dmabuf is in obj->export_dma_buf cache, because
+        * gem obj is still valid, and B could get dmabuf from this cache,
+        * but this dmabuf is invalid already, so B has to get a new dmabuf
+        * directly.
+        */
+       if (!atomic_long_read(&file->f_count))
+               return false;
+
+       return true;
+}
+EXPORT_SYMBOL(drm_prime_check_dmabuf_valid);
+
 static struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach,
                enum dma_data_direction dir)
 {
index c1b5619..c73fe7e 100644 (file)
@@ -56,6 +56,7 @@
 #include <linux/cdev.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
+#include <linux/dma-buf.h>
 #if defined(__alpha__) || defined(__powerpc__)
 #include <asm/pgtable.h>       /* For pte_wrprotect */
 #endif
@@ -1606,6 +1607,7 @@ void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv);
 int drm_prime_add_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t handle);
 int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf, uint32_t *handle);
 void drm_prime_remove_buf_handle(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf);
+bool drm_prime_check_dmabuf_valid(struct dma_buf *dmabuf);
 
 int drm_prime_add_dma_buf(struct drm_device *dev, struct drm_gem_object *obj);
 int drm_prime_lookup_obj(struct drm_device *dev, struct dma_buf *buf,