Implement automatic access management for mmap offsets for all GEM
drivers. This prevents user-space applications from "guessing" GEM BO
offsets and accessing buffers which they don't own.

Signed-off-by: David Herrmann <dh.herrmann at gmail.com>
---
 drivers/gpu/drm/drm_gem.c | 21 +++++++++++++++++----
 1 file changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c
index b5db89b..9d40ee3 100644
--- a/drivers/gpu/drm/drm_gem.c
+++ b/drivers/gpu/drm/drm_gem.c
@@ -240,6 +240,7 @@ drm_gem_handle_delete(struct drm_file *filp, u32 handle)
        spin_unlock(&filp->table_lock);

        drm_gem_remove_prime_handles(obj, filp);
+       drm_vma_node_revoke(&obj->vma_node, filp->filp);

        if (dev->driver->gem_close_object)
                dev->driver->gem_close_object(obj, filp);
@@ -279,15 +280,23 @@ drm_gem_handle_create(struct drm_file *file_priv,

        drm_gem_object_handle_reference(obj);

+       ret = drm_vma_node_allow(&obj->vma_node, file_priv->filp);
+       if (ret)
+               goto err_handle;
+
        if (dev->driver->gem_open_object) {
                ret = dev->driver->gem_open_object(obj, file_priv);
-               if (ret) {
-                       drm_gem_handle_delete(file_priv, *handlep);
-                       return ret;
-               }
+               if (ret)
+                       goto err_vma;
        }

        return 0;
+
+err_vma:
+       drm_vma_node_revoke(&obj->vma_node, file_priv->filp);
+err_handle:
+       drm_gem_handle_delete(file_priv, *handlep);
+       return ret;
 }
 EXPORT_SYMBOL(drm_gem_handle_create);

@@ -476,6 +485,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data)
        struct drm_device *dev = obj->dev;

        drm_gem_remove_prime_handles(obj, file_priv);
+       drm_vma_node_revoke(&obj->vma_node, file_priv->filp);

        if (dev->driver->gem_close_object)
                dev->driver->gem_close_object(obj, file_priv);
@@ -668,6 +678,9 @@ int drm_gem_mmap(struct file *filp, struct vm_area_struct 
*vma)
        if (!node) {
                mutex_unlock(&dev->struct_mutex);
                return drm_mmap(filp, vma);
+       } else if (!drm_vma_node_is_allowed(node, filp)) {
+               mutex_unlock(&dev->struct_mutex);
+               return -EACCES;
        }

        obj = container_of(node, struct drm_gem_object, vma_node);
-- 
1.8.3.2

Reply via email to