All of lore.kernel.org
 help / color / mirror / Atom feed
From: davidriley@chromium.org
To: Gerd Hoffmann <kraxel@redhat.com>,
	dri-devel@lists.freedesktop.org,
	virtualization@lists.linux-foundation.org
Cc: David Airlie <airlied@linux.ie>,
	linux-kernel@vger.kernel.org, Daniel Vetter <daniel@ffwll.ch>
Subject: [PATCH v2 3/4] drm/virtio: Fix cache entry creation race.
Date: Mon, 10 Jun 2019 14:18:09 -0700	[thread overview]
Message-ID: <20190610211810.253227-4-davidriley__11722.2495538712$1560201543$gmane$org@chromium.org> (raw)
In-Reply-To: <20190605234423.11348-1-davidriley@chromium.org>

From: David Riley <davidriley@chromium.org>

virtio_gpu_cmd_get_capset would check for the existence of an entry
under lock.  If it was not found, it would unlock and call
virtio_gpu_cmd_get_capset to create a new entry.  The new entry would
be added it to the list without checking if it was added by another
task during the period where the lock was not held resulting in
duplicate entries.

Compounding this issue, virtio_gpu_cmd_capset_cb would stop iterating
after find the first matching entry.  Multiple callbacks would modify
the first entry, but any subsequent entries and their associated waiters
would eventually timeout since they don't become valid, also wasting
memory along the way.

Signed-off-by: David Riley <davidriley@chromium.org>
---
 drivers/gpu/drm/virtio/virtgpu_vq.c | 22 +++++++++++++++++++++-
 1 file changed, 21 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index da71568adb9a..dd5ead2541c2 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -684,8 +684,11 @@ int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
 	struct virtio_gpu_vbuffer *vbuf;
 	int max_size;
 	struct virtio_gpu_drv_cap_cache *cache_ent;
+	struct virtio_gpu_drv_cap_cache *search_ent;
 	void *resp_buf;
 
+	*cache_p = NULL;
+
 	if (idx >= vgdev->num_capsets)
 		return -EINVAL;
 
@@ -716,9 +719,26 @@ int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
 	atomic_set(&cache_ent->is_valid, 0);
 	cache_ent->size = max_size;
 	spin_lock(&vgdev->display_info_lock);
-	list_add_tail(&cache_ent->head, &vgdev->cap_cache);
+	/* Search while under lock in case it was added by another task. */
+	list_for_each_entry(search_ent, &vgdev->cap_cache, head) {
+		if (search_ent->id == vgdev->capsets[idx].id &&
+		    search_ent->version == version) {
+			*cache_p = search_ent;
+			break;
+		}
+	}
+	if (!*cache_p)
+		list_add_tail(&cache_ent->head, &vgdev->cap_cache);
 	spin_unlock(&vgdev->display_info_lock);
 
+	if (*cache_p) {
+		/* Entry was found, so free everything that was just created. */
+		kfree(resp_buf);
+		kfree(cache_ent->caps_cache);
+		kfree(cache_ent);
+		return 0;
+	}
+
 	cmd_p = virtio_gpu_alloc_cmd_resp
 		(vgdev, &virtio_gpu_cmd_capset_cb, &vbuf, sizeof(*cmd_p),
 		 sizeof(struct virtio_gpu_resp_capset) + max_size,
-- 
2.22.0.rc2.383.gf4fbbf30c2-goog

  parent reply	other threads:[~2019-06-10 21:18 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-06-05 23:44 [PATCH 1/4] drm/virtio: Ensure cached capset entries are valid before copying davidriley
2019-06-05 23:44 ` davidriley
2019-06-05 23:44 ` [PATCH 2/4] drm/virtio: Wake up all waiters when capset response comes in davidriley
2019-06-05 23:44 ` davidriley
2019-06-05 23:44 ` [PATCH 3/4] drm/virtio: Fix cache entry creation race davidriley
2019-06-05 23:44 ` davidriley
2019-06-05 23:44 ` [PATCH 4/4] drm/virtio: Add memory barriers for capset cache davidriley
2019-06-05 23:44   ` davidriley
2019-06-06  7:41   ` Gerd Hoffmann
2019-06-06  7:41   ` Gerd Hoffmann
2019-06-05 23:44 ` davidriley
2019-06-10 21:18 ` [PATCH v2 0/4] drm/virtio: Ensure cached capset entries are valid before copying davidriley
2019-06-10 21:18 ` davidriley
2019-06-10 21:18 ` [PATCH v2 1/4] " davidriley
2019-06-10 21:18 ` davidriley
2019-06-10 21:18 ` [PATCH v2 2/4] drm/virtio: Wake up all waiters when capset response comes in davidriley
2019-06-10 21:18 ` davidriley
2019-06-10 21:18 ` davidriley [this message]
2019-06-10 21:18 ` [PATCH v2 3/4] drm/virtio: Fix cache entry creation race davidriley
2019-06-10 21:18 ` [PATCH v2 4/4] drm/virtio: Add memory barriers for capset cache davidriley
2019-06-13  6:59   ` Gerd Hoffmann
2019-06-13  6:59   ` Gerd Hoffmann
2019-06-13  6:59     ` Gerd Hoffmann
2019-06-10 21:18 ` davidriley

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='20190610211810.253227-4-davidriley__11722.2495538712$1560201543$gmane$org@chromium.org' \
    --to=davidriley@chromium.org \
    --cc=airlied@linux.ie \
    --cc=daniel@ffwll.ch \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=kraxel@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=virtualization@lists.linux-foundation.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.