diff options
author | Kristian Høgsberg <krh@redhat.com> | 2009-03-03 14:45:57 -0500 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2009-03-10 16:11:11 -0400 |
commit | b70d11da61d751ad968c6f686d83ac1b0ae41466 (patch) | |
tree | 388afdd8b085860e1f5ac7e3bc50b6d56ab1325e /drivers | |
parent | 99adcd9d67aaf04e28f5ae96df280f236bde4b66 (diff) |
drm: Return EINVAL on duplicate objects in execbuffer object list
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 17 |
2 files changed, 22 insertions, 1 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 17fa40858d26..9186d43be011 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -457,6 +457,12 @@ struct drm_i915_gem_object { | |||
457 | 457 | ||
458 | /** for phy allocated objects */ | 458 | /** for phy allocated objects */ |
459 | struct drm_i915_gem_phys_object *phys_obj; | 459 | struct drm_i915_gem_phys_object *phys_obj; |
460 | |||
461 | /** | ||
462 | * Used for checking the object doesn't appear more than once | ||
463 | * in an execbuffer object list. | ||
464 | */ | ||
465 | int in_execbuffer; | ||
460 | }; | 466 | }; |
461 | 467 | ||
462 | /** | 468 | /** |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 85685bfd12da..7bdcc752f139 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -2469,6 +2469,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
2469 | struct drm_i915_gem_exec_object *exec_list = NULL; | 2469 | struct drm_i915_gem_exec_object *exec_list = NULL; |
2470 | struct drm_gem_object **object_list = NULL; | 2470 | struct drm_gem_object **object_list = NULL; |
2471 | struct drm_gem_object *batch_obj; | 2471 | struct drm_gem_object *batch_obj; |
2472 | struct drm_i915_gem_object *obj_priv; | ||
2472 | int ret, i, pinned = 0; | 2473 | int ret, i, pinned = 0; |
2473 | uint64_t exec_offset; | 2474 | uint64_t exec_offset; |
2474 | uint32_t seqno, flush_domains; | 2475 | uint32_t seqno, flush_domains; |
@@ -2533,6 +2534,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
2533 | ret = -EBADF; | 2534 | ret = -EBADF; |
2534 | goto err; | 2535 | goto err; |
2535 | } | 2536 | } |
2537 | |||
2538 | obj_priv = object_list[i]->driver_private; | ||
2539 | if (obj_priv->in_execbuffer) { | ||
2540 | DRM_ERROR("Object %p appears more than once in object list\n", | ||
2541 | object_list[i]); | ||
2542 | ret = -EBADF; | ||
2543 | goto err; | ||
2544 | } | ||
2545 | obj_priv->in_execbuffer = true; | ||
2536 | } | 2546 | } |
2537 | 2547 | ||
2538 | /* Pin and relocate */ | 2548 | /* Pin and relocate */ |
@@ -2674,8 +2684,13 @@ err: | |||
2674 | for (i = 0; i < pinned; i++) | 2684 | for (i = 0; i < pinned; i++) |
2675 | i915_gem_object_unpin(object_list[i]); | 2685 | i915_gem_object_unpin(object_list[i]); |
2676 | 2686 | ||
2677 | for (i = 0; i < args->buffer_count; i++) | 2687 | for (i = 0; i < args->buffer_count; i++) { |
2688 | if (object_list[i]) { | ||
2689 | obj_priv = object_list[i]->driver_private; | ||
2690 | obj_priv->in_execbuffer = false; | ||
2691 | } | ||
2678 | drm_gem_object_unreference(object_list[i]); | 2692 | drm_gem_object_unreference(object_list[i]); |
2693 | } | ||
2679 | 2694 | ||
2680 | mutex_unlock(&dev->struct_mutex); | 2695 | mutex_unlock(&dev->struct_mutex); |
2681 | 2696 | ||