vmw_cmd_dma() locates the DMA suffix at

        (unsigned long) &cmd->body + header->size - sizeof(*suffix)

without checking that header->size is large enough to contain both
cmd->body and the suffix.  An undersized header makes the suffix
pointer underflow back into the previous command in the bounce
buffer.  The verifier later writes suffix->maximumOffset, clobbering
verified fields of an already-relocated earlier command -- a TOCTOU
on the device-visible command stream that lets one command rewrite
another's GMR id, surface id, or other authenticated fields.

Reject the command if the body is too small for the suffix to fit.

Fixes: 4e4ddd477743 ("drm/vmwgfx: Fix queries if no dma buffer thrashing is 
occuring.")
Cc: [email protected]
Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Zack Rusin <[email protected]>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index 2410d53a75aa..a9136a6523cb 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -1510,6 +1510,12 @@ static int vmw_cmd_dma(struct vmw_private *dev_priv,
        bool dirty;
 
        cmd = container_of(header, typeof(*cmd), header);
+
+       if (unlikely(header->size < sizeof(cmd->body) + sizeof(*suffix))) {
+               VMW_DEBUG_USER("Illegal SVGA_3D_CMD_SURFACE_DMA size.\n");
+               return -EINVAL;
+       }
+
        suffix = (SVGA3dCmdSurfaceDMASuffix *)((unsigned long) &cmd->body +
                                               header->size - sizeof(*suffix));
 
-- 
2.51.0

Reply via email to