From: Hui Peng <benquike@gmail.com>
To: airlied@redhat.com, kraxel@redhat.com,
dmitry.osipenko@collabora.com, gurchetansingh@chromium.org,
olvaffe@gmail.com, tzimmermann@suse.de
Cc: dri-devel@lists.freedesktop.org, virtualization@lists.linux.dev,
linux-kernel@vger.kernel.org
Subject: [PATCH] drm/virtio: fix 0-byte blob ZERO_SIZE_PTR, GEM leak, and context_init rollback
Date: Sat, 19 Sep 2026 21:52:32 +0000 [thread overview]
Message-ID: <20260919215232.3470178-1-benquike@gmail.com> (raw)
Fix multiple issues in virtio-gpu VRAM mapping, blob creation, and context
initialization:
1. In virtio_gpu_vram_mmap(), set vram->map_state = STATE_ERR if deferred
virtio_gpu_vram_map() fails so callers do not treat an unmapped VRAM
node as valid.
2. In verify_blob(), reject rc_blob->size == 0 or size values that wrap
PAGE_ALIGN() to prevent kvmalloc_array(0, ...) from returning
ZERO_SIZE_PTR.
3. In virtio_gpu_gem_create(), virtio_gpu_resource_create_ioctl(), and
virtio_gpu_resource_create_blob_ioctl(), use drm_gem_object_put()
instead of drm_gem_object_release() on error so the BO's free callback
is properly invoked.
4. In virtio_gpu_context_init_ioctl(), stage context parameters into local
variables and only commit them to vfpriv after all parameters and
ring_idx_mask have been validated.
Fixes: 16845c5d5409 ("drm/virtio: implement blob resources: implement vram object")
Fixes: 85c83ea915ed ("drm/virtio: implement context init: allocate an array of fence contexts")
Assisted-by: LLM
Signed-off-by: Hui Peng <benquike@gmail.com>
---
diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c
index 66c3f6f74e9c..d2f0b8a3f172 100644
--- a/drivers/gpu/drm/virtio/virtgpu_gem.c
+++ b/drivers/gpu/drm/virtio/virtgpu_gem.c
@@ -45,7 +45,7 @@ static int virtio_gpu_gem_create(struct drm_file *file,
ret = drm_gem_handle_create(file, &obj->base.base, &handle);
if (ret) {
- drm_gem_object_release(&obj->base.base);
+ drm_gem_object_put(&obj->base.base);
return ret;
}
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
index 3d8e4ccdb7c1..fb7225d91752 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -185,7 +185,7 @@ static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
ret = drm_gem_handle_create(file, obj, &handle);
if (ret) {
- drm_gem_object_release(obj);
+ drm_gem_object_put(obj);
return ret;
}
@@ -490,6 +490,9 @@ static int verify_blob(struct virtio_gpu_device *vgdev,
return -EINVAL;
}
+ if (rc_blob->size == 0 || rc_blob->size > ULONG_MAX - PAGE_SIZE + 1)
+ return -EINVAL;
+
params->blob_mem = rc_blob->blob_mem;
params->size = rc_blob->size;
params->blob = true;
@@ -557,14 +560,14 @@ static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev,
if (params.blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) {
ret = virtio_gpu_resource_assign_uuid(vgdev, bo);
if (ret) {
- drm_gem_object_release(obj);
+ drm_gem_object_put(obj);
return ret;
}
}
ret = drm_gem_handle_create(file, obj, &handle);
if (ret) {
- drm_gem_object_release(obj);
+ drm_gem_object_put(obj);
return ret;
}
@@ -616,6 +619,15 @@ static int virtio_gpu_context_init_ioctl(struct drm_device *dev,
goto out_unlock;
}
+ u32 context_init = vfpriv->context_init;
+ u32 num_rings = vfpriv->num_rings;
+ u64 ring_idx_mask = vfpriv->ring_idx_mask;
+ bool explicit_debug_name = vfpriv->explicit_debug_name;
+ bool num_rings_set = (vfpriv->base_fence_ctx != 0);
+ char debug_name[DEBUG_NAME_MAX_LEN];
+
+ memcpy(debug_name, vfpriv->debug_name, sizeof(debug_name));
+
for (i = 0; i < num_params; i++) {
param = ctx_set_params[i].param;
value = ctx_set_params[i].value;
@@ -633,16 +645,16 @@ static int virtio_gpu_context_init_ioctl(struct drm_device *dev,
}
/* Context capset ID already set */
- if (vfpriv->context_init &
+ if (context_init &
VIRTIO_GPU_CONTEXT_INIT_CAPSET_ID_MASK) {
ret = -EINVAL;
goto out_unlock;
}
- vfpriv->context_init |= value;
+ context_init |= value;
break;
case VIRTGPU_CONTEXT_PARAM_NUM_RINGS:
- if (vfpriv->base_fence_ctx) {
+ if (num_rings_set) {
ret = -EINVAL;
goto out_unlock;
}
@@ -652,30 +664,31 @@ static int virtio_gpu_context_init_ioctl(struct drm_device *dev,
goto out_unlock;
}
- vfpriv->base_fence_ctx = dma_fence_context_alloc(value);
- vfpriv->num_rings = value;
+ num_rings = value;
+ num_rings_set = true;
break;
case VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK:
- if (vfpriv->ring_idx_mask) {
+ if (ring_idx_mask) {
ret = -EINVAL;
goto out_unlock;
}
- vfpriv->ring_idx_mask = value;
+ ring_idx_mask = value;
break;
case VIRTGPU_CONTEXT_PARAM_DEBUG_NAME:
- if (vfpriv->explicit_debug_name) {
+ if (explicit_debug_name) {
ret = -EINVAL;
goto out_unlock;
}
- ret = strncpy_from_user(vfpriv->debug_name,
+ memset(debug_name, 0, sizeof(debug_name));
+ ret = strncpy_from_user(debug_name,
u64_to_user_ptr(value),
DEBUG_NAME_MAX_LEN - 1);
if (ret < 0)
goto out_unlock;
- vfpriv->explicit_debug_name = true;
+ explicit_debug_name = true;
ret = 0;
break;
default:
@@ -684,17 +697,28 @@ static int virtio_gpu_context_init_ioctl(struct drm_device *dev,
}
}
- if (vfpriv->ring_idx_mask) {
+ if (ring_idx_mask) {
valid_ring_mask = 0;
- for (i = 0; i < vfpriv->num_rings; i++)
+ for (i = 0; i < num_rings; i++)
valid_ring_mask |= 1ULL << i;
- if (~valid_ring_mask & vfpriv->ring_idx_mask) {
+ if (~valid_ring_mask & ring_idx_mask) {
ret = -EINVAL;
goto out_unlock;
}
}
+ vfpriv->context_init = context_init;
+ if (num_rings_set && !vfpriv->base_fence_ctx) {
+ vfpriv->base_fence_ctx = dma_fence_context_alloc(num_rings);
+ vfpriv->num_rings = num_rings;
+ }
+ vfpriv->ring_idx_mask = ring_idx_mask;
+ if (explicit_debug_name && !vfpriv->explicit_debug_name) {
+ memcpy(vfpriv->debug_name, debug_name, sizeof(vfpriv->debug_name));
+ vfpriv->explicit_debug_name = true;
+ }
+
virtio_gpu_create_context_locked(vgdev, vfpriv);
virtio_gpu_notify(vgdev);
diff --git a/drivers/gpu/drm/virtio/virtgpu_vram.c b/drivers/gpu/drm/virtio/virtgpu_vram.c
index 5b4a3ab81cd5..aaeae38afc0e 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vram.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vram.c
@@ -248,7 +248,10 @@ void virtio_gpu_vram_map_deferred(struct virtio_gpu_object_vram *vram)
return;
mutex_lock(&map_lock);
- if (!drm_mm_node_allocated(&vram->vram_node))
- virtio_gpu_vram_map(&vram->base);
+ if (!drm_mm_node_allocated(&vram->vram_node)) {
+ vram->map_state = STATE_INITIALIZING;
+ if (virtio_gpu_vram_map(&vram->base))
+ vram->map_state = STATE_ERR;
+ }
mutex_unlock(&map_lock);
}
next reply other threads:[~2026-09-19 21:52 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-19 21:52 Hui Peng [this message]
2026-09-19 22:02 ` [PATCH] drm/virtio: fix 0-byte blob ZERO_SIZE_PTR, GEM leak, and context_init rollback sashiko-bot
2026-09-20 18:45 ` Dmitry Osipenko
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=20260919215232.3470178-1-benquike@gmail.com \
--to=benquike@gmail.com \
--cc=airlied@redhat.com \
--cc=dmitry.osipenko@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=gurchetansingh@chromium.org \
--cc=kraxel@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=olvaffe@gmail.com \
--cc=tzimmermann@suse.de \
--cc=virtualization@lists.linux.dev \
/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.