From: Daniel Vetter <daniel@ffwll.ch>
To: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Dave Airlie <airlied@redhat.com>,
intel-gfx@lists.freedesktop.org, dri-devel@lists.freedesktop.org
Subject: Re: [PATCH] drm/syncobj: Stop reusing the same struct file for all syncobj -> fd
Date: Tue, 19 Dec 2017 13:28:49 +0100 [thread overview]
Message-ID: <20171219122849.GF26573@phenom.ffwll.local> (raw)
In-Reply-To: <20171219120700.27797-1-chris@chris-wilson.co.uk>
On Tue, Dec 19, 2017 at 12:07:00PM +0000, Chris Wilson wrote:
> The vk cts test:
> dEQP-VK.api.external.semaphore.opaque_fd.export_multiple_times_temporary
>
> triggers a lot of
> VFS: Close: file count is 0
>
> Dave pointed out that clearing the syncobj->file from
> drm_syncobj_file_release() was sufficient to silence the test, but that
> opens a can of worm since we assumed that the syncobj->file was never
> unset. Stop trying to reuse the same struct file for every fd pointing
> to the drm_syncobj, and allocate one file for each fd instead.
It's worse: syncobj->file points to a refcounted thing, and we never did
grab a reference for it. This is a classic use-after-free thing :-)
> Reported-by: Dave Airlie <airlied@redhat.com>
> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Dave Airlie <airlied@redhat.com>
Assuming it doesn't break the vk testsuite:
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Also an igt for this would be nice:
1. create syncobj
2. export to fd
3. close fd, note that now syncobj->file points to a freed struct file
4. reexport -> BOOM
Cheers, Daniel
> ---
> drivers/gpu/drm/drm_syncobj.c | 74 +++++++++++++++----------------------------
> include/drm/drm_syncobj.h | 4 ---
> 2 files changed, 26 insertions(+), 52 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
> index 131695915acd..0cca2e792719 100644
> --- a/drivers/gpu/drm/drm_syncobj.c
> +++ b/drivers/gpu/drm/drm_syncobj.c
> @@ -399,23 +399,6 @@ static const struct file_operations drm_syncobj_file_fops = {
> .release = drm_syncobj_file_release,
> };
>
> -static int drm_syncobj_alloc_file(struct drm_syncobj *syncobj)
> -{
> - struct file *file = anon_inode_getfile("syncobj_file",
> - &drm_syncobj_file_fops,
> - syncobj, 0);
> - if (IS_ERR(file))
> - return PTR_ERR(file);
> -
> - drm_syncobj_get(syncobj);
> - if (cmpxchg(&syncobj->file, NULL, file)) {
> - /* lost the race */
> - fput(file);
> - }
> -
> - return 0;
> -}
> -
> /**
> * drm_syncobj_get_fd - get a file descriptor from a syncobj
> * @syncobj: Sync object to export
> @@ -427,21 +410,24 @@ static int drm_syncobj_alloc_file(struct drm_syncobj *syncobj)
> */
> int drm_syncobj_get_fd(struct drm_syncobj *syncobj, int *p_fd)
> {
> - int ret;
> + struct file *file;
> int fd;
>
> fd = get_unused_fd_flags(O_CLOEXEC);
> if (fd < 0)
> return fd;
>
> - if (!syncobj->file) {
> - ret = drm_syncobj_alloc_file(syncobj);
> - if (ret) {
> - put_unused_fd(fd);
> - return ret;
> - }
> + file = anon_inode_getfile("syncobj_file",
> + &drm_syncobj_file_fops,
> + syncobj, 0);
> + if (IS_ERR(file)) {
> + put_unused_fd(fd);
> + return PTR_ERR(file);
> }
> - fd_install(fd, syncobj->file);
> +
> + drm_syncobj_get(syncobj);
> + fd_install(fd, file);
> +
> *p_fd = fd;
> return 0;
> }
> @@ -461,31 +447,24 @@ static int drm_syncobj_handle_to_fd(struct drm_file *file_private,
> return ret;
> }
>
> -static struct drm_syncobj *drm_syncobj_fdget(int fd)
> -{
> - struct file *file = fget(fd);
> -
> - if (!file)
> - return NULL;
> - if (file->f_op != &drm_syncobj_file_fops)
> - goto err;
> -
> - return file->private_data;
> -err:
> - fput(file);
> - return NULL;
> -};
> -
> static int drm_syncobj_fd_to_handle(struct drm_file *file_private,
> int fd, u32 *handle)
> {
> - struct drm_syncobj *syncobj = drm_syncobj_fdget(fd);
> + struct drm_syncobj *syncobj;
> + struct file *file;
> int ret;
>
> - if (!syncobj)
> + file = fget(fd);
> + if (!file)
> return -EINVAL;
>
> + if (file->f_op != &drm_syncobj_file_fops) {
> + fput(file);
> + return -EINVAL;
> + }
> +
> /* take a reference to put in the idr */
> + syncobj = file->private_data;
> drm_syncobj_get(syncobj);
>
> idr_preload(GFP_KERNEL);
> @@ -494,12 +473,11 @@ static int drm_syncobj_fd_to_handle(struct drm_file *file_private,
> spin_unlock(&file_private->syncobj_table_lock);
> idr_preload_end();
>
> - if (ret < 0) {
> - fput(syncobj->file);
> - return ret;
> - }
> - *handle = ret;
> - return 0;
> + if (ret > 0)
> + *handle = ret;
> +
> + fput(file);
> + return ret;
> }
>
> static int drm_syncobj_import_sync_file_fence(struct drm_file *file_private,
> diff --git a/include/drm/drm_syncobj.h b/include/drm/drm_syncobj.h
> index 3980602472c0..ca5bf7d12d0b 100644
> --- a/include/drm/drm_syncobj.h
> +++ b/include/drm/drm_syncobj.h
> @@ -56,10 +56,6 @@ struct drm_syncobj {
> * @lock: Protects &cb_list and write-locks &fence.
> */
> spinlock_t lock;
> - /**
> - * @file: A file backing for this syncobj.
> - */
> - struct file *file;
> };
>
> typedef void (*drm_syncobj_func_t)(struct drm_syncobj *syncobj,
> --
> 2.15.1
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/intel-gfx
--
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch
_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/intel-gfx
next prev parent reply other threads:[~2017-12-19 12:28 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-12-19 11:30 [PATCH] drm/syncobj: reset file ptr to NULL when released Dave Airlie
2017-12-19 12:03 ` Chris Wilson
2017-12-19 12:05 ` Daniel Vetter
2017-12-19 12:07 ` [PATCH] drm/syncobj: Stop reusing the same struct file for all syncobj -> fd Chris Wilson
2017-12-19 12:28 ` Daniel Vetter [this message]
2017-12-21 2:42 ` Dave Airlie
2017-12-21 7:51 ` [Intel-gfx] " Chris Wilson
2017-12-21 9:28 ` [PATCH v2] " Chris Wilson
2017-12-21 10:50 ` Chris Wilson
2017-12-22 3:05 ` Dave Airlie
2017-12-22 9:28 ` Chris Wilson
2017-12-19 13:34 ` ✓ Fi.CI.BAT: success for " Patchwork
2017-12-19 16:02 ` ✓ Fi.CI.IGT: " Patchwork
2017-12-21 10:13 ` ✓ Fi.CI.BAT: success for drm/syncobj: Stop reusing the same struct file for all syncobj -> fd (rev2) Patchwork
2017-12-21 12:06 ` ✗ Fi.CI.IGT: warning " Patchwork
-- strict thread matches above, loose matches on Subject: below --
2018-03-26 19:00 [PATCH] drm/syncobj: Stop reusing the same struct file for all syncobj -> fd Jason Ekstrand
2018-03-27 6:37 ` Jani Nikula
2018-03-27 6:37 ` Jani Nikula
2018-03-27 7:29 ` Greg KH
2018-03-27 7:29 ` Greg KH
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=20171219122849.GF26573@phenom.ffwll.local \
--to=daniel@ffwll.ch \
--cc=airlied@redhat.com \
--cc=chris@chris-wilson.co.uk \
--cc=dri-devel@lists.freedesktop.org \
--cc=intel-gfx@lists.freedesktop.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.