From: Ben Widawsky <ben@bwidawsk.net>
To: Chris Wilson <chris@chris-wilson.co.uk>
Cc: intel-gfx@lists.freedesktop.org, stable@vger.kernel.org
Subject: Re: [PATCH] drm/i915: Prevent double unref following alloc failure during execbuffer
Date: Wed, 4 Dec 2013 09:23:24 -0800 [thread overview]
Message-ID: <20131204172323.GB2350@bwidawsk.net> (raw)
In-Reply-To: <1386150778-9066-1-git-send-email-chris@chris-wilson.co.uk>
On Wed, Dec 04, 2013 at 09:52:58AM +0000, Chris Wilson wrote:
> Whilst looking up the objects required for an execbuffer, an untimely
> allocation failure in creating the vma results in the object being
> unreferenced from two lists. The ownership during the lookup is meant to
> be moved from the list of objects being looked to the vma, and this
> double unreference upon error results in a use-after-free.
>
> Fixes regression from
> commit 27173f1f95db5e74ceb35fe9a2f2f348ea11bac9
> Author: Ben Widawsky <ben@bwidawsk.net>
> Date: Wed Aug 14 11:38:36 2013 +0200
>
> drm/i915: Convert execbuf code to use vmas
>
> Based on the fix by Ben Widawsky.
A note on why this is an improvement over my fix would have been nice. I
had implemented something similar too, but found my eventual patch to be
a little easier to understand.
My real gripe is, I had already sent off my patch to be tested by QA -
and they give me about a 2d turnaround (not including weekends), which
means the soonest I could get this tested and get results is next Wed.
So if there is no improvement, I'd really appreciate this as a cleanup
on top of my patch.
>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Ben Widawsky <ben@bwidawsk.net>
> Cc: stable@vger.kernel.org
> ---
> drivers/gpu/drm/i915/i915_gem_execbuffer.c | 24 ++++++++++++++++--------
> 1 file changed, 16 insertions(+), 8 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> index c7af37187dee..5663b873a1aa 100644
> --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
> @@ -94,7 +94,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
> struct drm_i915_private *dev_priv = vm->dev->dev_private;
> struct drm_i915_gem_object *obj;
> struct list_head objects;
> - int i, ret = 0;
> + int i, ret;
>
> INIT_LIST_HEAD(&objects);
> spin_lock(&file->table_lock);
> @@ -107,7 +107,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
> DRM_DEBUG("Invalid object handle %d at index %d\n",
> exec[i].handle, i);
> ret = -ENOENT;
> - goto out;
> + goto err;
> }
>
> if (!list_empty(&obj->obj_exec_link)) {
> @@ -115,7 +115,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
> DRM_DEBUG("Object %p [handle %d, index %d] appears more than once in object list\n",
> obj, exec[i].handle, i);
> ret = -EINVAL;
> - goto out;
> + goto err;
> }
>
> drm_gem_object_reference(&obj->base);
> @@ -124,7 +124,7 @@ eb_lookup_vmas(struct eb_vmas *eb,
> spin_unlock(&file->table_lock);
>
> i = 0;
> - list_for_each_entry(obj, &objects, obj_exec_link) {
> + while (!list_empty(&objects)) {
> struct i915_vma *vma;
> struct i915_address_space *bind_vm = vm;
>
> @@ -136,6 +136,10 @@ eb_lookup_vmas(struct eb_vmas *eb,
> (i == (args->buffer_count - 1))))
> bind_vm = &dev_priv->gtt.base;
>
> + obj = list_first_entry(&objects,
> + struct drm_i915_gem_object,
> + obj_exec_link);
> +
> /*
> * NOTE: We can leak any vmas created here when something fails
> * later on. But that's no issue since vma_unbind can deal with
> @@ -148,10 +152,12 @@ eb_lookup_vmas(struct eb_vmas *eb,
> if (IS_ERR(vma)) {
> DRM_DEBUG("Failed to lookup VMA\n");
> ret = PTR_ERR(vma);
> - goto out;
> + goto err;
> }
>
> + /* Transfer ownership from objects to the vma */
> list_add_tail(&vma->exec_list, &eb->vmas);
> + list_del_init(&obj->obj_exec_link);
>
> vma->exec_entry = &exec[i];
> if (eb->and < 0) {
> @@ -165,16 +171,18 @@ eb_lookup_vmas(struct eb_vmas *eb,
> ++i;
> }
>
> + return 0;
>
> -out:
> +
> +err:
> while (!list_empty(&objects)) {
> obj = list_first_entry(&objects,
> struct drm_i915_gem_object,
> obj_exec_link);
> list_del_init(&obj->obj_exec_link);
> - if (ret)
> - drm_gem_object_unreference(&obj->base);
> + drm_gem_object_unreference(&obj->base);
> }
> + /* objects already transfered to the vma will be reaped by eb_destroy */
> return ret;
> }
>
> --
> 1.8.5
>
--
Ben Widawsky, Intel Open Source Technology Center
next prev parent reply other threads:[~2013-12-04 17:23 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-12-04 1:28 [PATCH] drm/i915: Fixed bad refcounting on execbuf failures Ben Widawsky
2013-12-04 9:52 ` [PATCH] drm/i915: Prevent double unref following alloc failure during execbuffer Chris Wilson
2013-12-04 17:23 ` Ben Widawsky [this message]
2013-12-04 17:37 ` Chris Wilson
2013-12-11 21:22 ` [Intel-gfx] " Daniel Vetter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20131204172323.GB2350@bwidawsk.net \
--to=ben@bwidawsk.net \
--cc=chris@chris-wilson.co.uk \
--cc=intel-gfx@lists.freedesktop.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox