drm: Return EINVAL on duplicate objects in execbuffer object list
authorKristian Høgsberg <krh@redhat.com>
Tue, 3 Mar 2009 19:45:57 +0000 (14:45 -0500)
committerEric Anholt <eric@anholt.net>
Tue, 10 Mar 2009 20:11:11 +0000 (13:11 -0700)
If userspace passes an object list with the same object appearing more
than once, we end up hitting the BUG_ON() in
i915_gem_object_set_to_gpu_domain() as it gets called a second time
for the same object.

Signed-off-by: Kristian Høgsberg <krh@redhat.com>
Signed-off-by: Eric Anholt <eric@anholt.net>
drivers/gpu/drm/i915/i915_drv.h
drivers/gpu/drm/i915/i915_gem.c

index 17fa408..9186d43 100644 (file)
@@ -457,6 +457,12 @@ struct drm_i915_gem_object {
 
        /** for phy allocated objects */
        struct drm_i915_gem_phys_object *phys_obj;
+
+       /**
+        * Used for checking the object doesn't appear more than once
+        * in an execbuffer object list.
+        */
+       int in_execbuffer;
 };
 
 /**
index 85685bf..7bdcc75 100644 (file)
@@ -2469,6 +2469,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
        struct drm_i915_gem_exec_object *exec_list = NULL;
        struct drm_gem_object **object_list = NULL;
        struct drm_gem_object *batch_obj;
+       struct drm_i915_gem_object *obj_priv;
        int ret, i, pinned = 0;
        uint64_t exec_offset;
        uint32_t seqno, flush_domains;
@@ -2533,6 +2534,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
                        ret = -EBADF;
                        goto err;
                }
+
+               obj_priv = object_list[i]->driver_private;
+               if (obj_priv->in_execbuffer) {
+                       DRM_ERROR("Object %p appears more than once in object list\n",
+                                  object_list[i]);
+                       ret = -EBADF;
+                       goto err;
+               }
+               obj_priv->in_execbuffer = true;
        }
 
        /* Pin and relocate */
@@ -2674,8 +2684,13 @@ err:
        for (i = 0; i < pinned; i++)
                i915_gem_object_unpin(object_list[i]);
 
-       for (i = 0; i < args->buffer_count; i++)
+       for (i = 0; i < args->buffer_count; i++) {
+               if (object_list[i]) {
+                       obj_priv = object_list[i]->driver_private;
+                       obj_priv->in_execbuffer = false;
+               }
                drm_gem_object_unreference(object_list[i]);
+       }
 
        mutex_unlock(&dev->struct_mutex);