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/gpu | |
| 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/gpu')
| -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 | ||
