]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Aug 2026 12:19:38 +0000 (14:19 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 5 Aug 2026 12:19:38 +0000 (14:19 +0200)
added patches:
drm-vmwgfx-bound-dma-command-body-size-against-suffix-pointer.patch
drm-vmwgfx-drop-dma_buf-reference-on-foreign-fd-prime-import.patch
drm-vmwgfx-fix-guest_memory_dirty-bitfield-clobbered-as-size.patch
drm-vmwgfx-reject-dx_bind_query-without-a-dx-context.patch
drm-vmwgfx-use-check_add_overflow-for-shader-size-offset-bound.patch
drm-vmwgfx-validate-draw_primitives-header-size-before-division.patch
drm-vmwgfx-validate-external-bo-copy-bounds-for-both-stride-paths.patch

queue-6.6/drm-vmwgfx-bound-dma-command-body-size-against-suffix-pointer.patch [new file with mode: 0644]
queue-6.6/drm-vmwgfx-drop-dma_buf-reference-on-foreign-fd-prime-import.patch [new file with mode: 0644]
queue-6.6/drm-vmwgfx-fix-guest_memory_dirty-bitfield-clobbered-as-size.patch [new file with mode: 0644]
queue-6.6/drm-vmwgfx-reject-dx_bind_query-without-a-dx-context.patch [new file with mode: 0644]
queue-6.6/drm-vmwgfx-use-check_add_overflow-for-shader-size-offset-bound.patch [new file with mode: 0644]
queue-6.6/drm-vmwgfx-validate-draw_primitives-header-size-before-division.patch [new file with mode: 0644]
queue-6.6/drm-vmwgfx-validate-external-bo-copy-bounds-for-both-stride-paths.patch [new file with mode: 0644]
queue-6.6/series

diff --git a/queue-6.6/drm-vmwgfx-bound-dma-command-body-size-against-suffix-pointer.patch b/queue-6.6/drm-vmwgfx-bound-dma-command-body-size-against-suffix-pointer.patch
new file mode 100644 (file)
index 0000000..21a55bc
--- /dev/null
@@ -0,0 +1,49 @@
+From f4f1db96bfd68b81053693ba53405b6f510ac16c Mon Sep 17 00:00:00 2001
+From: Zack Rusin <zack.rusin@broadcom.com>
+Date: Tue, 5 May 2026 18:22:28 -0400
+Subject: drm/vmwgfx: bound DMA command body size against suffix pointer
+
+From: Zack Rusin <zack.rusin@broadcom.com>
+
+commit f4f1db96bfd68b81053693ba53405b6f510ac16c upstream.
+
+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: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4.7
+Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
+Reviewed-by: Ian Forbes <ian.forbes@broadcom.com>
+Link: https://patch.msgid.link/20260505222728.519626-8-zack.rusin@broadcom.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c |    6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+@@ -1527,6 +1527,12 @@ static int vmw_cmd_dma(struct vmw_privat
+       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));
diff --git a/queue-6.6/drm-vmwgfx-drop-dma_buf-reference-on-foreign-fd-prime-import.patch b/queue-6.6/drm-vmwgfx-drop-dma_buf-reference-on-foreign-fd-prime-import.patch
new file mode 100644 (file)
index 0000000..8f7a171
--- /dev/null
@@ -0,0 +1,52 @@
+From f739416dc555fa205a785e5135d73fa39b26f35d Mon Sep 17 00:00:00 2001
+From: Zack Rusin <zack.rusin@broadcom.com>
+Date: Tue, 5 May 2026 18:22:26 -0400
+Subject: drm/vmwgfx: drop dma_buf reference on foreign-fd prime import
+
+From: Zack Rusin <zack.rusin@broadcom.com>
+
+commit f739416dc555fa205a785e5135d73fa39b26f35d upstream.
+
+ttm_prime_fd_to_handle() returns -ENOSYS when the imported fd's
+dma_buf->ops do not match the ttm_object_device's ops, but does so
+without releasing the reference acquired by dma_buf_get().  Any
+unprivileged renderD client passing a non-vmwgfx prime fd through the
+DRM_VMW_GB_SURFACE_REF{,_EXT} path leaks one dma_buf reference per
+call and indefinitely pins the foreign exporter's GEM resources.
+
+Funnel the error path through the existing dma_buf_put() so the
+reference is always dropped.
+
+Fixes: 65981f7681ab ("drm/ttm: Add a minimal prime implementation for ttm base objects")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4.7
+Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
+Reviewed-by: Ian Forbes <ian.forbes@broadcom.com>
+Link: https://patch.msgid.link/20260505222728.519626-6-zack.rusin@broadcom.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/vmwgfx/ttm_object.c |    7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vmwgfx/ttm_object.c
++++ b/drivers/gpu/drm/vmwgfx/ttm_object.c
+@@ -551,14 +551,17 @@ int ttm_prime_fd_to_handle(struct ttm_ob
+       if (IS_ERR(dma_buf))
+               return PTR_ERR(dma_buf);
+-      if (dma_buf->ops != &tdev->ops)
+-              return -ENOSYS;
++      if (dma_buf->ops != &tdev->ops) {
++              ret = -ENOSYS;
++              goto out;
++      }
+       prime = (struct ttm_prime_object *) dma_buf->priv;
+       base = &prime->base;
+       *handle = base->handle;
+       ret = ttm_ref_object_add(tfile, base, NULL, false);
++out:
+       dma_buf_put(dma_buf);
+       return ret;
diff --git a/queue-6.6/drm-vmwgfx-fix-guest_memory_dirty-bitfield-clobbered-as-size.patch b/queue-6.6/drm-vmwgfx-fix-guest_memory_dirty-bitfield-clobbered-as-size.patch
new file mode 100644 (file)
index 0000000..41b86a4
--- /dev/null
@@ -0,0 +1,59 @@
+From 83195b778f2d109a3a4f3ffaba4dce7e4cdb58aa Mon Sep 17 00:00:00 2001
+From: Zack Rusin <zack.rusin@broadcom.com>
+Date: Tue, 5 May 2026 18:22:22 -0400
+Subject: drm/vmwgfx: fix guest_memory_dirty bitfield clobbered as size
+
+From: Zack Rusin <zack.rusin@broadcom.com>
+
+commit 83195b778f2d109a3a4f3ffaba4dce7e4cdb58aa upstream.
+
+Two sites in vmwgfx_resource.c assign boolean literals to
+res->guest_memory_size, which is an unsigned long allocation-size
+field; the intended target is the adjacent res->guest_memory_dirty
+bitfield.  After the assignments the field holds 0 or 1 instead of
+the resource's MOB allocation size:
+
+  - vmw_resource_release()       writes 0 (false), and
+  - vmw_resource_unbind_list()   writes 1 (true).
+
+Subsequent revalidation paths read guest_memory_size when computing
+the dirty page range (vmw_bo_dirty_transfer_to_res()) and the buffer
+allocation size (vmw_resource_buf_alloc()), producing zero-length
+walks or wrap-around ranges that read or write past the MOB bitmap.
+The dirty-tracking intent of the original code (mark the resource as
+dirtied since the last sync) is also lost, since guest_memory_dirty
+is never updated.
+
+Rename both assignments to guest_memory_dirty.
+
+Fixes: 668b206601c5 ("drm/vmwgfx: Stop using raw ttm_buffer_object's")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4.7
+Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
+Reviewed-by: Ian Forbes <ian.forbes@broadcom.com>
+Link: https://patch.msgid.link/20260505222728.519626-2-zack.rusin@broadcom.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_resource.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
+@@ -134,7 +134,7 @@ static void vmw_resource_release(struct
+                       val_buf.num_shared = 0;
+                       res->func->unbind(res, false, &val_buf);
+               }
+-              res->guest_memory_size = false;
++              res->guest_memory_dirty = false;
+               vmw_resource_mob_detach(res);
+               if (res->dirty)
+                       res->func->dirty_free(res);
+@@ -764,7 +764,7 @@ void vmw_resource_unbind_list(struct vmw
+               if (!WARN_ON_ONCE(!res->func->unbind))
+                       (void) res->func->unbind(res, res->res_dirty, &val_buf);
+-              res->guest_memory_size = true;
++              res->guest_memory_dirty = true;
+               res->res_dirty = false;
+               vmw_resource_mob_detach(res);
+       }
diff --git a/queue-6.6/drm-vmwgfx-reject-dx_bind_query-without-a-dx-context.patch b/queue-6.6/drm-vmwgfx-reject-dx_bind_query-without-a-dx-context.patch
new file mode 100644 (file)
index 0000000..97dc19f
--- /dev/null
@@ -0,0 +1,57 @@
+From 55ec09c9ce10b1272802c7ab6c1be2ea0dbc68db Mon Sep 17 00:00:00 2001
+From: Zack Rusin <zack.rusin@broadcom.com>
+Date: Tue, 5 May 2026 18:22:23 -0400
+Subject: drm/vmwgfx: reject DX_BIND_QUERY without a DX context
+
+From: Zack Rusin <zack.rusin@broadcom.com>
+
+commit 55ec09c9ce10b1272802c7ab6c1be2ea0dbc68db upstream.
+
+vmw_cmd_dx_bind_query() unconditionally dereferences
+sw_context->dx_ctx_node->ctx.  Userspace can trigger a NULL pointer
+dereference from any render-node fd by submitting an execbuf with
+dx_context_handle == SVGA3D_INVALID_ID and a SVGA_3D_CMD_DX_BIND_QUERY
+opcode in the command stream: dx_ctx_node is left NULL and the kernel
+oopses on the assignment.  The same NULL is then re-read in
+vmw_resources_reserve() via vmw_context_get_dx_query_mob().
+
+All sibling DX handlers fail-close on a missing dx_ctx_node using
+VMW_GET_CTX_NODE().  Use the same pattern here, returning -EINVAL up
+front before any relocation state is published.
+
+Fixes: 9c079b8ce8bf ("drm/vmwgfx: Adapt execbuf to the new validation api")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4.7
+Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
+Reviewed-by: Ian Forbes <ian.forbes@broadcom.com>
+Link: https://patch.msgid.link/20260505222728.519626-3-zack.rusin@broadcom.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c |    6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+@@ -1289,9 +1289,13 @@ static int vmw_cmd_dx_bind_query(struct
+                                SVGA3dCmdHeader *header)
+ {
+       VMW_DECLARE_CMD_VAR(*cmd, SVGA3dCmdDXBindQuery);
++      struct vmw_ctx_validation_info *ctx_node = VMW_GET_CTX_NODE(sw_context);
+       struct vmw_bo *vmw_bo;
+       int ret;
++      if (!ctx_node)
++              return -EINVAL;
++
+       cmd = container_of(header, typeof(*cmd), header);
+       /*
+@@ -1305,7 +1309,7 @@ static int vmw_cmd_dx_bind_query(struct
+               return ret;
+       sw_context->dx_query_mob = vmw_bo;
+-      sw_context->dx_query_ctx = sw_context->dx_ctx_node->ctx;
++      sw_context->dx_query_ctx = ctx_node->ctx;
+       return 0;
+ }
diff --git a/queue-6.6/drm-vmwgfx-use-check_add_overflow-for-shader-size-offset-bound.patch b/queue-6.6/drm-vmwgfx-use-check_add_overflow-for-shader-size-offset-bound.patch
new file mode 100644 (file)
index 0000000..8f60752
--- /dev/null
@@ -0,0 +1,90 @@
+From 54d56d5b42d2e4c72ba6e365e9774da90698aa22 Mon Sep 17 00:00:00 2001
+From: Zack Rusin <zack.rusin@broadcom.com>
+Date: Tue, 5 May 2026 18:22:32 -0400
+Subject: drm/vmwgfx: use check_add_overflow for shader size+offset bound
+
+From: Zack Rusin <zack.rusin@broadcom.com>
+
+commit 54d56d5b42d2e4c72ba6e365e9774da90698aa22 upstream.
+
+vmw_shader_define() validates the user-supplied shader window against
+its backing buffer with
+
+       (u64)buffer->tbo.base.size < (u64)size + (u64)offset
+
+drm_vmw_shader_create_arg::offset is __u64 in the uapi; when it is
+near U64_MAX the unsigned addition wraps and the resulting tiny value
+passes the check.  The unbounded offset is then stored in
+res->guest_memory_offset and forwarded to host SVGA shader-create
+commands.
+
+Use check_add_overflow() to detect the wrap and compare the resulting
+endpoint against the buffer size.
+
+Fixes: 668b206601c5 ("drm/vmwgfx: Stop using raw ttm_buffer_object's")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4.7
+Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
+Reviewed-by: Ian Forbes <ian.forbes@broadcom.com>
+Link: https://patch.msgid.link/20260505222728.519626-12-zack.rusin@broadcom.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_shader.c |   13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
+@@ -25,6 +25,8 @@
+  *
+  **************************************************************************/
++#include <linux/overflow.h>
++
+ #include <drm/ttm/ttm_placement.h>
+ #include "vmwgfx_binding.h"
+@@ -685,7 +687,7 @@ int vmw_shader_destroy_ioctl(struct drm_
+ static int vmw_user_shader_alloc(struct vmw_private *dev_priv,
+                                struct vmw_bo *buffer,
+                                size_t shader_size,
+-                               size_t offset,
++                               u64 offset,
+                                SVGA3dShaderType shader_type,
+                                uint8_t num_input_sig,
+                                uint8_t num_output_sig,
+@@ -739,7 +741,7 @@ out:
+ static struct vmw_resource *vmw_shader_alloc(struct vmw_private *dev_priv,
+                                            struct vmw_bo *buffer,
+                                            size_t shader_size,
+-                                           size_t offset,
++                                           u64 offset,
+                                            SVGA3dShaderType shader_type)
+ {
+       struct vmw_shader *shader;
+@@ -768,7 +770,7 @@ out_err:
+ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv,
+                            enum drm_vmw_shader_type shader_type_drm,
+-                           u32 buffer_handle, size_t size, size_t offset,
++                           u32 buffer_handle, size_t size, u64 offset,
+                            uint8_t num_input_sig, uint8_t num_output_sig,
+                            uint32_t *shader_handle)
+ {
+@@ -779,13 +781,16 @@ static int vmw_shader_define(struct drm_
+       int ret;
+       if (buffer_handle != SVGA3D_INVALID_ID) {
++              u64 end;
++
+               ret = vmw_user_bo_lookup(file_priv, buffer_handle, &buffer);
+               if (unlikely(ret != 0)) {
+                       VMW_DEBUG_USER("Couldn't find buffer for shader creation.\n");
+                       return ret;
+               }
+-              if ((u64)buffer->tbo.base.size < (u64)size + (u64)offset) {
++              if (check_add_overflow((u64)size, (u64)offset, &end) ||
++                  end > buffer->tbo.base.size) {
+                       VMW_DEBUG_USER("Illegal buffer- or shader size.\n");
+                       ret = -EINVAL;
+                       goto out_bad_arg;
diff --git a/queue-6.6/drm-vmwgfx-validate-draw_primitives-header-size-before-division.patch b/queue-6.6/drm-vmwgfx-validate-draw_primitives-header-size-before-division.patch
new file mode 100644 (file)
index 0000000..ce87878
--- /dev/null
@@ -0,0 +1,54 @@
+From 85891d174707d8bddcec7a888fb4e1d17def34f3 Mon Sep 17 00:00:00 2001
+From: Zack Rusin <zack.rusin@broadcom.com>
+Date: Tue, 5 May 2026 18:22:27 -0400
+Subject: drm/vmwgfx: validate DRAW_PRIMITIVES header size before division
+
+From: Zack Rusin <zack.rusin@broadcom.com>
+
+commit 85891d174707d8bddcec7a888fb4e1d17def34f3 upstream.
+
+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: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4.7
+Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
+Reviewed-by: Ian Forbes <ian.forbes@broadcom.com>
+Link: https://patch.msgid.link/20260505222728.519626-7-zack.rusin@broadcom.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c |    8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
+@@ -1588,11 +1588,17 @@ static int vmw_cmd_draw(struct vmw_priva
+       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)) {
diff --git a/queue-6.6/drm-vmwgfx-validate-external-bo-copy-bounds-for-both-stride-paths.patch b/queue-6.6/drm-vmwgfx-validate-external-bo-copy-bounds-for-both-stride-paths.patch
new file mode 100644 (file)
index 0000000..67985ec
--- /dev/null
@@ -0,0 +1,131 @@
+From 706c93c5813caabbb0d0a576c017d15aeec2c113 Mon Sep 17 00:00:00 2001
+From: Zack Rusin <zack.rusin@broadcom.com>
+Date: Tue, 5 May 2026 18:22:33 -0400
+Subject: drm/vmwgfx: validate external BO copy bounds for both stride paths
+
+From: Zack Rusin <zack.rusin@broadcom.com>
+
+commit 706c93c5813caabbb0d0a576c017d15aeec2c113 upstream.
+
+vmw_external_bo_copy() trusts caller-supplied offsets, strides, and
+heights and operates on imported dma-buf vmaps:
+
+  - The equal-stride memcpy() bound was clamped after subtracting the
+    offsets from dst_size and src_size; an offset larger than the BO
+    size wraps the unsigned subtraction to a huge value and the
+    resulting memcpy() runs off the end of the vmap.  dst_stride *
+    height is also a u32 multiplication that can overflow.
+  - The non-equal-stride row-by-row path had no bound at all.  The
+    loop touches bytes through offset + (height - 1) * stride +
+    width_in_bytes, with only a WARN_ON(dst_stride < width_in_bytes),
+    and could likewise step past the end of either mapping.
+
+The offsets and strides are derived from STDU/SOU plane state, so a
+configured CRTC submitting a crafted atomic commit on an imported
+framebuffer can reach this path.
+
+Validate the exact row-copy endpoint against each BO's size up front
+using check_mul_overflow() and check_add_overflow().  Use the bulk
+memcpy() path only when width_in_bytes covers the whole stride;
+otherwise copy one row at a time so partial-row updates near the bottom
+of a framebuffer remain valid.  Also reject zero strides and stride <
+width_in_bytes, both of which the row-by-row path cannot represent
+safely.
+
+Fixes: 50f119925091 ("drm/vmwgfx: Fix prime with external buffers")
+Cc: stable@vger.kernel.org
+Assisted-by: Claude:claude-opus-4.7
+Signed-off-by: Zack Rusin <zack.rusin@broadcom.com>
+Reviewed-by: Ian Forbes <ian.forbes@broadcom.com>
+Link: https://patch.msgid.link/20260505222728.519626-13-zack.rusin@broadcom.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/vmwgfx/vmwgfx_blit.c |   39 +++++++++++++++++++++++++++--------
+ 1 file changed, 31 insertions(+), 8 deletions(-)
+
+--- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
++++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
+@@ -30,6 +30,7 @@
+ #include "vmwgfx_bo.h"
+ #include <linux/highmem.h>
++#include <linux/overflow.h>
+ /*
+  * Template that implements find_first_diff() for a generic
+@@ -463,19 +464,42 @@ static int vmw_external_bo_copy(struct v
+               container_of(dst->tbo.bdev, struct vmw_private, bdev);
+       size_t dst_size = dst->tbo.resource->size;
+       size_t src_size = src->tbo.resource->size;
++      size_t dst_end, src_end;
+       struct iosys_map dst_map = {0};
+       struct iosys_map src_map = {0};
++      bool dst_mapped = false;
++      bool src_mapped = false;
+       int ret, i;
+       int x_in_bytes;
+       u8 *vsrc;
+       u8 *vdst;
++      if (!height || !width_in_bytes)
++              return 0;
++
++      if (!dst_stride || !src_stride)
++              return -EINVAL;
++      if (dst_stride < width_in_bytes || src_stride < width_in_bytes)
++              return -EINVAL;
++      if (check_mul_overflow((size_t)dst_stride, (size_t)height - 1, &dst_end) ||
++          check_add_overflow(dst_end, (size_t)width_in_bytes, &dst_end) ||
++          check_add_overflow((size_t)dst_offset, dst_end, &dst_end) ||
++          dst_end > dst_size ||
++          check_mul_overflow((size_t)src_stride, (size_t)height - 1, &src_end) ||
++          check_add_overflow(src_end, (size_t)width_in_bytes, &src_end) ||
++          check_add_overflow((size_t)src_offset, src_end, &src_end) ||
++          src_end > src_size) {
++              drm_dbg_driver(&vmw->drm, "Out-of-bounds external BO copy\n");
++              return -EINVAL;
++      }
++
+       vsrc = map_external(src, &src_map);
+       if (!vsrc) {
+               drm_dbg_driver(&vmw->drm, "Wasn't able to map src\n");
+               ret = -ENOMEM;
+               goto out;
+       }
++      src_mapped = true;
+       vdst = map_external(dst, &dst_map);
+       if (!vdst) {
+@@ -483,16 +507,13 @@ static int vmw_external_bo_copy(struct v
+               ret = -ENOMEM;
+               goto out;
+       }
++      dst_mapped = true;
+       vsrc += src_offset;
+       vdst += dst_offset;
+-      if (src_stride == dst_stride) {
+-              dst_size -= dst_offset;
+-              src_size -= src_offset;
+-              memcpy(vdst, vsrc,
+-                     min(dst_stride * height, min(dst_size, src_size)));
++      if (src_stride == dst_stride && width_in_bytes == dst_stride) {
++              memcpy(vdst, vsrc, dst_stride * (size_t)height);
+       } else {
+-              WARN_ON(dst_stride < width_in_bytes);
+               for (i = 0; i < height; ++i) {
+                       memcpy(vdst, vsrc, width_in_bytes);
+                       vsrc += src_stride;
+@@ -508,8 +529,10 @@ static int vmw_external_bo_copy(struct v
+       ret = 0;
+ out:
+-      unmap_external(src, &src_map);
+-      unmap_external(dst, &dst_map);
++      if (src_mapped)
++              unmap_external(src, &src_map);
++      if (dst_mapped)
++              unmap_external(dst, &dst_map);
+       return ret;
+ }
index 0790c383883dca9857b74e9b458669e366ec8356..d13e9ba759d3ff079f4bc15e63707cc70deef0b8 100644 (file)
@@ -194,3 +194,10 @@ drm-amdkfd-fix-missing-authorization-check-in-kfd_ioc_dbg_trap_disable.patch
 drm-amdkfd-fix-qid-bit-leak-in-pqm_create_queue.patch
 drm-amdkfd-handle-invalid-event-type-in-criu-event-restore.patch
 drm-amdkfd-hold-event_mutex-while-checkpointing-criu-events.patch
+drm-vmwgfx-fix-guest_memory_dirty-bitfield-clobbered-as-size.patch
+drm-vmwgfx-reject-dx_bind_query-without-a-dx-context.patch
+drm-vmwgfx-drop-dma_buf-reference-on-foreign-fd-prime-import.patch
+drm-vmwgfx-validate-draw_primitives-header-size-before-division.patch
+drm-vmwgfx-bound-dma-command-body-size-against-suffix-pointer.patch
+drm-vmwgfx-use-check_add_overflow-for-shader-size-offset-bound.patch
+drm-vmwgfx-validate-external-bo-copy-bounds-for-both-stride-paths.patch