Hello, Thank you for the review and for pointing out the kernel-version, patch-format, and maintainer-CC issues.
I retested the BO-unpin reproducer using a Linux 7.3-based kernel in the same QEMU environment. The same failure still occurs during PRIME/GEM cleanup: vmw_bo_pin_reserved() is called with pin=false, ttm_bo_validate() returns -EINVAL, and the following BUG_ON() causes a kernel BUG. The relevant 7.3 kernel report excerpt is included below (pointer values omitted): [ 72.910575] [BO_PIN_TRACE] enter ... pin=1 pin_count=0 ... mem_type=0 placement=0x10 [ 72.910624] [BO_PIN_TRACE] before-validate pin=1 old_mem_type=0 target_mem_type=0 flags=0x10 [ 72.910652] [BO_PIN_TRACE] after-validate ret=0 old_mem_type=0 new_mem_type=0 ... [ 72.910680] [BO_PIN_TRACE] done pin=1 pin_count=1 mem_type=0 [ 72.916071] [BO_PIN_TRACE] enter ... pin=0 pin_count=1 ... mem_type=0 placement=0x10 [ 72.916147] [BO_PIN_TRACE] before-validate pin=0 old_mem_type=0 target_mem_type=0 flags=0x10 [ 72.916201] [BO_PIN_TRACE] after-validate ret=-22 old_mem_type=0 new_mem_type=0 ... [ 72.918818] ------------[ cut here ]------------ [ 72.918841] kernel BUG at drivers/gpu/drm/vmwgfx/vmwgfx_bo.c:342! [ 72.918892] Oops: invalid opcode: 0000 [#1] SMP NOPTI [ 72.933292] CPU: 1 UID: 0 PID: 346 Comm: repro_vmwgfx_bo Not tainted 7.3.0-dirty #2 PREEMPT(lazy) [ 72.937912] RIP: 0010:vmw_bo_pin_reserved+0x36d/0x380 [ 72.947235] RBP: 00000000ffffffea Call Trace: vmw_gem_object_unpin drm_gem_map_detach dma_buf_detach drm_prime_gem_destroy drm_gem_shmem_release drm_gem_object_handle_put_unlocked drm_gem_object_release_handle idr_for_each drm_gem_release drm_file_free drm_close_helper drm_release __fput ____fput task_work_run do_exit do_group_exit __x64_sys_exit_group [ 72.990254] Fixing recursive fault but reboot is needed! The corresponding userspace program had successfully opened the DRM nodes, created a dumb GEM buffer, exported/imported its PRIME fd, performed the GEM flink/open/close operations, and then exited. The final `exit_group()` teardown released the remaining GEM/PRIME references and entered the cleanup stack shown above. The three attached patches address three distinct vmwgfx failures: 1. `0001-drm-vmwgfx-unpin-BOs-without-revalidating-placement.patch` fixes the reproduced cleanup BUG above. During PRIME detach, the GEM unpin callback calls vmw_bo_pin_reserved(..., false); the function unnecessarily calls ttm_bo_validate(), gets -EINVAL, and turns it into a kernel BUG with BUG_ON(). The patch skips revalidation for unpin and keeps it for pin. 2. `0002-drm-vmwgfx-validate-FIFO-state-before-reserving-comm.patch` addresses FIFO-reservation crashes: a missing local FIFO state can be dereferenced, or invalid device-provided MIN/MAX/NEXT_CMD/STOP offsets can be used in ring arithmetic to form an invalid FIFO pointer. The patch checks the state and offsets before computing/returning the command pointer. This issue has not been reproduced on the 7.3 test kernel. 3. `0003-drm-vmwgfx-reject-PRIME-export-without-TTM-backing.patch` addresses the PRIME get_sg_table NULL dereference. During PRIME fd-to-handle import, the map-attachment path reaches vmw_gem_object_get_sg_table(); if bo->ttm is NULL, container_of() yields a NULL-based vmw_ttm_tt and reading vsgt.sgt faults at NULL+0x88. The patch returns -EINVAL when the TTM backing is absent. This issue has not been reproduced on the 7.3 test kernel. Regards, Yuhang Pan [email protected]
From 046cb4a4218075f8b3d8c290fede659143e6f98d Mon Sep 17 00:00:00 2001 From: Yuhang Pan <[email protected]> Date: Thu, 29 Oct 2026 15:16:51 +0800 Subject: [PATCH] drm/vmwgfx: unpin BOs without revalidating placement Unpinning a buffer object does not change its placement. Avoid calling ttm_bo_validate() on the unpin path, where a placement validation failure currently triggers BUG_ON() and crashes the kernel during PRIME cleanup. Keep validation on the pin path, where it is needed to establish the requested placement before pinning. Signed-off-by: Yuhang Pan <[email protected]> --- drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index 9c7a73c..14d28e2 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -308,6 +308,11 @@ void vmw_bo_pin_reserved(struct vmw_bo *vbo, bool pin) if (pin == !!bo->pin_count) return; + if (!pin) { + ttm_bo_unpin(bo); + return; + } + pl.fpfn = 0; pl.lpfn = 0; pl.mem_type = bo->resource->mem_type; @@ -321,10 +326,7 @@ void vmw_bo_pin_reserved(struct vmw_bo *vbo, bool pin) BUG_ON(ret != 0 || bo->resource->mem_type != old_mem_type); - if (pin) - ttm_bo_pin(bo); - else - ttm_bo_unpin(bo); + ttm_bo_pin(bo); } /**
From d92d555250dcd3560f08fa43a548b24ee460f79e Mon Sep 17 00:00:00 2001 From: Yuhang Pan <[email protected]> Date: Thu, 29 Oct 2026 15:16:51 +0800 Subject: [PATCH] drm/vmwgfx: validate FIFO state before reserving commands Reject missing FIFO state and invalid ring offsets before using device provided FIFO positions to construct a command pointer. Signed-off-by: Yuhang Pan <[email protected]> --- drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c index d932e38..02987d3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c @@ -282,15 +282,22 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv, uint32_t max; uint32_t min; uint32_t next_cmd; - uint32_t reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE; + u32 reserveable; int ret; + if (unlikely(!fifo_state || !fifo_mem)) + return NULL; + reserveable = fifo_state->capabilities & SVGA_FIFO_CAP_RESERVE; mutex_lock(&fifo_state->fifo_mutex); max = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_MAX); min = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_MIN); next_cmd = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_NEXT_CMD); - if (unlikely(bytes >= (max - min))) + if (unlikely(min < PAGE_SIZE || min >= max || + max > dev_priv->fifo_mem_size || + next_cmd < min || next_cmd >= max || + ((min | max | next_cmd) & 3) || + bytes >= (max - min))) goto out_err; BUG_ON(fifo_state->reserved_size != 0); @@ -303,6 +310,9 @@ static void *vmw_local_fifo_reserve(struct vmw_private *dev_priv, bool need_bounce = false; bool reserve_in_place = false; + if (unlikely(stop < min || stop >= max || (stop & 3))) + goto out_err; + if (next_cmd >= stop) { if (likely((next_cmd + bytes < max || (next_cmd + bytes == max && stop > min))))
From 3d719a0d708d3c26852d6cfb2838f4fa8f5aafdb Mon Sep 17 00:00:00 2001 From: Yuhang Pan <[email protected]> Date: Thu, 29 Oct 2026 15:16:51 +0800 Subject: [PATCH] drm/vmwgfx: reject PRIME export without TTM backing The PRIME get_sg_table callback requires vmwgfx TTM backing. Return an error when the backing translation table is absent instead of deriving a vmw_ttm_tt pointer from NULL. Signed-off-by: Yuhang Pan <[email protected]> --- drivers/gpu/drm/vmwgfx/vmwgfx_gem.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c index 39f8c46..dd1e6b7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c @@ -70,8 +70,12 @@ static void vmw_gem_object_unpin(struct drm_gem_object *obj) static struct sg_table *vmw_gem_object_get_sg_table(struct drm_gem_object *obj) { struct ttm_buffer_object *bo = drm_gem_ttm_of_gem(obj); - struct vmw_ttm_tt *vmw_tt = - container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm); + struct vmw_ttm_tt *vmw_tt; + + if (unlikely(!bo->ttm)) + return ERR_PTR(-EINVAL); + + vmw_tt = container_of(bo->ttm, struct vmw_ttm_tt, dma_ttm); if (vmw_tt->vsgt.sgt) return vmw_tt->vsgt.sgt;
