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 device model, I observed faults in the FIFO command reservation path. The issue has two related manifestations: a NULL dereference when the FIFO state is absent, and an invalid kernel write when FIFO ring offsets read from the device are outside the mapped FIFO region. For the NULL-state case, the userspace operation was DRM_IOCTL_VMW_CREATE_CONTEXT. The path is: __x64_sys_ioctl() -> vmw_unlocked_ioctl() -> vmw_generic_ioctl() -> drm_ioctl() -> vmw_context_define_ioctl() -> vmw_context_define() -> vmw_context_init() -> VMW_CMD_RESERVE() -> vmw_cmd_ctx_reserve() -> vmw_local_fifo_reserve() In vmw_local_fifo_reserve(), the FIFO state is read from dev_priv->fifo and its capabilities are accessed before checking that the pointer is valid. When the device has no FIFO state, this access faults at offset 0x24: BUG: kernel NULL pointer dereference, address: 0000000000000024 RIP: 0010:vmw_cmd_ctx_reserve+0x102/0x600 CR2: 0000000000000024 In the invalid-offset case, DRM_IOCTL_VMW_FENCE_EVENT reaches vmw_cmd_send_fence(), which reserves a FIFO command and writes it at the address derived from SVGA_FIFO_NEXT_CMD. The call path is: __x64_sys_ioctl() -> vmw_unlocked_ioctl() -> vmw_generic_ioctl() -> drm_ioctl() -> vmw_fence_event_ioctl() -> vmw_execbuf_fence_commands() -> vmw_cmd_send_fence() -> vmw_local_fifo_reserve() -> vmw_local_fifo_commit() The observed invalid write was: BUG: unable to handle page fault for address: ffa000009e85232c RIP: 0010:vmw_cmd_send_fence+0x16e/0x290 CR2: ffa000009e85232c The report did not capture the raw SVGA_FIFO_NEXT_CMD value, so I cannot state its exact value. The driver currently validates the requested command size but does not first verify that FIFO MIN/MAX/NEXT_CMD/STOP form aligned offsets within the mapped FIFO memory. This patch checks for missing FIFO state and memory, validates those ring boundaries, and rejects invalid offsets before using them to construct a command pointer. 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 <[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)))) -- 2.34.1 Regards, Yuhang Pan [email protected]
