vmw_cmd_draw() computes

        maxnum = (header->size - sizeof(cmd->body)) / sizeof(*decl);

where header->size is u32 and is taken straight from the user-supplied
command stream.  When header->size is less than sizeof(cmd->body) the
unsigned subtraction wraps to nearly 4 GiB, producing a huge maxnum.
Any user-controlled cmd->body.numVertexDecls then passes the bound and
the loop dereferences decl[i] far past the end of the kernel command
bounce buffer, producing an out-of-bounds read of kernel memory.

Reject undersized headers up front.

Fixes: 7a73ba7469cb ("drm/vmwgfx: Use TTM handles instead of SIDs as user-space 
surface handles.")
Cc: [email protected]
Assisted-by: Claude:claude-opus-4.7
Signed-off-by: Zack Rusin <[email protected]>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c 
b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
index b07f052474d0..2410d53a75aa 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
@@ -1571,11 +1571,17 @@ static int vmw_cmd_draw(struct vmw_private *dev_priv,
        uint32_t maxnum;
        int ret;
 
+       cmd = container_of(header, typeof(*cmd), header);
+
+       if (unlikely(header->size < sizeof(cmd->body))) {
+               VMW_DEBUG_USER("Illegal DRAW_PRIMITIVES header size.\n");
+               return -EINVAL;
+       }
+
        ret = vmw_cmd_cid_check(dev_priv, sw_context, header);
        if (unlikely(ret != 0))
                return ret;
 
-       cmd = container_of(header, typeof(*cmd), header);
        maxnum = (header->size - sizeof(cmd->body)) / sizeof(*decl);
 
        if (unlikely(cmd->body.numVertexDecls > maxnum)) {
-- 
2.51.0

Reply via email to