7.2-stable review patch. If anyone has any objections, please let me know. ------------------ From: Zack Rusin commit 21bc51cb89ced74d6645a138cc2f21184bc75094 upstream. Validate the pitch, alongside the box dimensions before trying to copy data from the underlying surface. Fixes possible out of bounds reads with cursor snooping. Fixes: 2ac863719e51 ("vmwgfx: Snoop DMA transfers with non-covering sizes") Cc: stable@vger.kernel.org Reported-by: Youness HFA Signed-off-by: Zack Rusin Reviewed-by: Maaz Mombasawala Link: https://patch.msgid.link/20260809204515.211045-1-zack.rusin@broadcom.com Signed-off-by: Greg Kroah-Hartman --- drivers/gpu/drm/vmwgfx/vmwgfx_cursor_plane.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cursor_plane.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cursor_plane.c @@ -324,6 +324,7 @@ void vmw_kms_cursor_snoop(struct vmw_sur unsigned long kmap_num; SVGA3dCopyBox *box; u32 box_count; + u64 src_extent; void *virtual; bool is_iomem; struct vmw_dma_cmd { @@ -335,6 +336,8 @@ void vmw_kms_cursor_snoop(struct vmw_sur vmw_surface_get_desc(VMW_CURSOR_SNOOP_FORMAT); const u32 image_pitch = VMW_CURSOR_SNOOP_WIDTH * desc->pitchBytesPerBlock; + BUILD_BUG_ON(sizeof(*srf->snooper.image) != desc->pitchBytesPerBlock); + cmd = container_of(header, struct vmw_dma_cmd, header); /* No snooper installed, nothing to copy */ @@ -372,8 +375,19 @@ void vmw_kms_cursor_snoop(struct vmw_sur return; } + if (box->w == 0 || box->h == 0) + return; + + src_extent = (u64)(box->h - 1) * cmd->dma.guest.pitch + + (u64)box->w * desc->pitchBytesPerBlock; + if (src_extent > bo->base.size) { + DRM_ERROR("Cursor snoop source of %llu bytes exceeds the %zu byte buffer\n", + src_extent, bo->base.size); + return; + } + kmap_offset = cmd->dma.guest.ptr.offset >> PAGE_SHIFT; - kmap_num = (VMW_CURSOR_SNOOP_HEIGHT * image_pitch) >> PAGE_SHIFT; + kmap_num = PFN_UP(src_extent); ret = ttm_bo_reserve(bo, true, false, NULL); if (unlikely(ret != 0)) { @@ -387,14 +401,16 @@ void vmw_kms_cursor_snoop(struct vmw_sur virtual = ttm_kmap_obj_virtual(&map, &is_iomem); - if (box->w == VMW_CURSOR_SNOOP_WIDTH && cmd->dma.guest.pitch == image_pitch) { + if (box->w == VMW_CURSOR_SNOOP_WIDTH && + box->h == VMW_CURSOR_SNOOP_HEIGHT && + cmd->dma.guest.pitch == image_pitch) { memcpy(srf->snooper.image, virtual, VMW_CURSOR_SNOOP_HEIGHT * image_pitch); } else { - /* Image is unsigned pointer. */ + /* The destination stride is in pixels. */ for (i = 0; i < box->h; i++) - memcpy(srf->snooper.image + i * image_pitch, - virtual + i * cmd->dma.guest.pitch, + memcpy(srf->snooper.image + i * VMW_CURSOR_SNOOP_WIDTH, + virtual + (size_t)i * cmd->dma.guest.pitch, box->w * desc->pitchBytesPerBlock); } srf->snooper.id++;