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;

Reply via email to