reject PRIME export without TTM backing

From: 潘煜杭

Date: Thu Oct 29 2026 - 04:33:29 EST


Hello,

GPT-5 assisted with the initial analysis and drafting the proposed fix. I am
responsible for this report and patch.

While fuzzing the vmwgfx PRIME import path, I observed a kernel NULL pointer
dereference in vmw_gem_object_get_sg_table(). The userspace operation was
DRM_IOCTL_PRIME_FD_TO_HANDLE. The call path was:

__x64_sys_ioctl()
-> vmw_unlocked_ioctl()
-> vmw_generic_ioctl()
-> drm_ioctl()
-> drm_prime_fd_to_handle_ioctl()
-> vmw_prime_fd_to_handle()
-> drm_gem_prime_fd_to_handle()
-> drm_gem_prime_import_dev()
-> dma_buf_map_attachment()
-> drm_gem_map_dma_buf()
-> vmw_gem_object_get_sg_table()

The vmwgfx callback obtains the TTM buffer object and uses bo->ttm as the
embedded dma_ttm member of struct vmw_ttm_tt. In the crashing path, bo->ttm
was NULL. container_of() consequently produced a NULL-based vmw_ttm_tt
pointer, and reading vmw_tt->vsgt.sgt faulted at offset 0x88:

BUG: kernel NULL pointer dereference, address: 0000000000000088
RIP: 0010:vmw_gem_object_get_sg_table+0x2f/0xa0
RBP: 0000000000000000
CR2: 0000000000000088

The faulting instruction reads from [RBP + 0x88]; with RBP equal to zero,
this matches the reported address. The callback requires a vmwgfx TTM
translation table, so it must reject an object without bo->ttm before
container_of() and member access. This patch returns -EINVAL in that case.

The patch below is against the Linux 7.3 source tree; it
applies cleanly and passes checkpatch.pl --strict.

Assisted-by: OpenAI Codex (GPT-5)
Signed-off-by: Yuhang Pan <242270054@xxxxxxxxxx>
---
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;
--
2.34.1

Regards,
Yuhang Pan
242270054@xxxxxxxxxx