All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] drm/vmwgfx: Validate vmw_surface_metadata::array_size
@ 2026-06-23 19:33 Ian Forbes
  2026-06-23 21:22 ` sashiko-bot
  2026-07-01 18:31 ` Maaz Mombasawala
  0 siblings, 2 replies; 3+ messages in thread
From: Ian Forbes @ 2026-06-23 19:33 UTC (permalink / raw)
  To: dri-devel
  Cc: bcm-kernel-feedback-list, zack.rusin, maaz.mombasawala,
	Ian Forbes

This field comes from userspace and should be validated against specific
limits depending on which Shader Model (SM) is available.

Fixes: 504901dbb0b5 ("drm/vmwgfx: Refactor surface_define to use vmw_surface_metadata")
Signed-off-by: Ian Forbes <ian.forbes@broadcom.com>
---
 drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 22 +++++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
index b2d3927b5567..bd0563741e89 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
@@ -78,7 +78,7 @@ static int vmw_gb_surface_unbind(struct vmw_resource *res,
 static int vmw_gb_surface_destroy(struct vmw_resource *res);
 static int
 vmw_gb_surface_define_internal(struct drm_device *dev,
-			       struct drm_vmw_gb_surface_create_ext_req *req,
+			       const  struct drm_vmw_gb_surface_create_ext_req *req,
 			       struct drm_vmw_gb_surface_create_rep *rep,
 			       struct drm_file *file_priv);
 static int
@@ -1503,7 +1503,7 @@ int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, void *data,
  */
 static int
 vmw_gb_surface_define_internal(struct drm_device *dev,
-			       struct drm_vmw_gb_surface_create_ext_req *req,
+			       const  struct drm_vmw_gb_surface_create_ext_req *req,
 			       struct drm_vmw_gb_surface_create_rep *rep,
 			       struct drm_file *file_priv)
 {
@@ -1521,9 +1521,21 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
 				req->base.svga3d_flags);
 
 	/* array_size must be null for non-GL3 host. */
-	if (req->base.array_size > 0 && !has_sm4_context(dev_priv)) {
-		VMW_DEBUG_USER("SM4 surface not supported.\n");
-		return -EINVAL;
+	if (req->base.array_size > 0) {
+		if (has_sm5_context(dev_priv)) {
+			if (req->base.array_size > SVGA3D_SM5_MAX_SURFACE_ARRAYSIZE) {
+				VMW_DEBUG_USER("Invalid Surface Array Size.\n");
+				return -EINVAL;
+			}
+		} else if (has_sm4_context(dev_priv)) {
+			if (req->base.array_size > SVGA3D_SM4_MAX_SURFACE_ARRAYSIZE) {
+				VMW_DEBUG_USER("Invalid Surface Array Size.\n");
+				return -EINVAL;
+			}
+		} else {
+			VMW_DEBUG_USER("SM4+ surface not supported.\n");
+			return -EINVAL;
+		}
 	}
 
 	if (!has_sm4_1_context(dev_priv)) {
-- 
2.54.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] drm/vmwgfx: Validate vmw_surface_metadata::array_size
  2026-06-23 19:33 [PATCH] drm/vmwgfx: Validate vmw_surface_metadata::array_size Ian Forbes
@ 2026-06-23 21:22 ` sashiko-bot
  2026-07-01 18:31 ` Maaz Mombasawala
  1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-06-23 21:22 UTC (permalink / raw)
  To: Ian Forbes; +Cc: dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Integer overflows and missing bounds checks in surface size computations lead to severe buffer undersizing and out-of-bounds memory access.
- [Critical] Integer truncation from `unsigned long` to `uint32_t` causes critical buffer undersize when allocating GEM objects for large surfaces.
--

commit 50825a4076b6af2aa84715573bcdaf84763db731
Author: Ian Forbes <ian.forbes@broadcom.com>

drm/vmwgfx: Validate vmw_surface_metadata::array_size

This field comes from userspace and should be validated against specific
limits depending on which Shader Model (SM) is available.

> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
> index b2d3927b55673..bd0563741e89d 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
> @@ -1521,9 +1521,21 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
>  				req->base.svga3d_flags);
>  
>  	/* array_size must be null for non-GL3 host. */
> -	if (req->base.array_size > 0 && !has_sm4_context(dev_priv)) {
> -		VMW_DEBUG_USER("SM4 surface not supported.\n");
> -		return -EINVAL;
> +	if (req->base.array_size > 0) {
> +		if (has_sm5_context(dev_priv)) {
> +			if (req->base.array_size > SVGA3D_SM5_MAX_SURFACE_ARRAYSIZE) {
> +				VMW_DEBUG_USER("Invalid Surface Array Size.\n");
> +				return -EINVAL;
> +			}
> +		} else if (has_sm4_context(dev_priv)) {
> +			if (req->base.array_size > SVGA3D_SM4_MAX_SURFACE_ARRAYSIZE) {
> +				VMW_DEBUG_USER("Invalid Surface Array Size.\n");
> +				return -EINVAL;
> +			}
> +		} else {
> +			VMW_DEBUG_USER("SM4+ surface not supported.\n");
> +			return -EINVAL;
> +		}
>  	}

[Severity: Critical]
This is a pre-existing issue, but does the surface size computation lack
sufficient bounds checking for non-scanout formats?

If a user-space process issues a surface define ioctl for a non-scanout
format with extremely large base_size dimensions, vmw_gb_surface_define()
skips checking the maximum boundaries:

drivers/gpu/drm/vmwgfx/vmwgfx_surface.c:vmw_gb_surface_define() {
    ...
    } else {
        const SVGA3dSurfaceDesc *desc =
            vmw_surface_get_desc(req->format);

        if (desc->blockDesc == SVGA3DBLOCKDESC_NONE) {
            VMW_DEBUG_USER("Invalid surface format.\n");
            return -EINVAL;
        }
    }
    ...
}

This allows massive dimensions to be processed without validation by
vmw_surface_calculate_pitch() and vmw_surface_get_serialized_size(), where
the 32-bit multiplications can wrap around:

drivers/gpu/drm/vmwgfx/vmw_surface_cache.h:vmw_surface_calculate_pitch() {
    ...
    pitch = blocks.width * desc->pitchBytesPerBlock;
    ...
}

Because this wraps around to a small u32 value, it can evade the U32_MAX
clamp in vmw_surface_get_serialized_size_extended(), resulting in a
tiny guest_memory_size allocation while the original massive dimensions
remain in the surface metadata. Can this lead to severe guest physical
memory corruption from out-of-bounds access?

[ ... ]

>  	} else if (req->base.drm_surface_flags &
>  		   (drm_vmw_surface_flag_create_buffer |
>  		    drm_vmw_surface_flag_coherent)) {
>  		ret = vmw_gem_object_create_with_handle(dev_priv, file_priv,
>  							res->guest_memory_size,
>  							&backup_handle,
>  							&res->guest_memory_bo);
>  	}

[Severity: Critical]
This isn't a bug introduced by this patch, but does the guest memory size
get silently truncated when creating the GEM object for large surfaces?

If a user-space process requests a large surface that causes
vmw_surface_get_serialized_size_extended() to return exactly U32_MAX
(the clamped maximum), and sets the SVGA3D_SURFACE_BIND_STREAM_OUTPUT flag,
vmw_gb_surface_define() unconditionally adds 16 bytes to the size:

drivers/gpu/drm/vmwgfx/vmwgfx_surface.c:vmw_gb_surface_define() {
    ...
    if (metadata->flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT)
        srf->res.guest_memory_size += sizeof(SVGA3dDXSOState);
    ...
}

This pushes the 64-bit value to 0x10000000F (U32_MAX + 16). When this is
passed to vmw_gem_object_create_with_handle(), the size appears to be
truncated because the function signature takes a 32-bit size:

drivers/gpu/drm/vmwgfx/vmwgfx_gem.c:vmw_gem_object_create_with_handle() {
    int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv,
                                          struct drm_file *filp,
                                          uint32_t size,
                                          uint32_t *handle,
                                          struct vmw_bo **p_vbo)
    ...
}

This truncation wraps the 0x10000000F size down to just 15 bytes. Is it
possible for this to allocate a tiny 15-byte GEM object for a surface
that the metadata considers to be 4GB, leading to massive out-of-bounds
memory overrides during surface operations?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260623193314.506257-1-ian.forbes@broadcom.com?part=1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] drm/vmwgfx: Validate vmw_surface_metadata::array_size
  2026-06-23 19:33 [PATCH] drm/vmwgfx: Validate vmw_surface_metadata::array_size Ian Forbes
  2026-06-23 21:22 ` sashiko-bot
@ 2026-07-01 18:31 ` Maaz Mombasawala
  1 sibling, 0 replies; 3+ messages in thread
From: Maaz Mombasawala @ 2026-07-01 18:31 UTC (permalink / raw)
  To: Ian Forbes, dri-devel; +Cc: bcm-kernel-feedback-list, zack.rusin

On 6/23/26 12:33 PM, Ian Forbes wrote:
> This field comes from userspace and should be validated against specific
> limits depending on which Shader Model (SM) is available.
> 
> Fixes: 504901dbb0b5 ("drm/vmwgfx: Refactor surface_define to use vmw_surface_metadata")
> Signed-off-by: Ian Forbes <ian.forbes@broadcom.com>
> ---
>  drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 22 +++++++++++++++++-----
>  1 file changed, 17 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
> index b2d3927b5567..bd0563741e89 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
> @@ -78,7 +78,7 @@ static int vmw_gb_surface_unbind(struct vmw_resource *res,
>  static int vmw_gb_surface_destroy(struct vmw_resource *res);
>  static int
>  vmw_gb_surface_define_internal(struct drm_device *dev,
> -			       struct drm_vmw_gb_surface_create_ext_req *req,
> +			       const  struct drm_vmw_gb_surface_create_ext_req *req,
>  			       struct drm_vmw_gb_surface_create_rep *rep,
>  			       struct drm_file *file_priv);
>  static int
> @@ -1503,7 +1503,7 @@ int vmw_gb_surface_reference_ext_ioctl(struct drm_device *dev, void *data,
>   */
>  static int
>  vmw_gb_surface_define_internal(struct drm_device *dev,
> -			       struct drm_vmw_gb_surface_create_ext_req *req,
> +			       const  struct drm_vmw_gb_surface_create_ext_req *req,
>  			       struct drm_vmw_gb_surface_create_rep *rep,
>  			       struct drm_file *file_priv)
>  {
> @@ -1521,9 +1521,21 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
>  				req->base.svga3d_flags);
>  
>  	/* array_size must be null for non-GL3 host. */
> -	if (req->base.array_size > 0 && !has_sm4_context(dev_priv)) {
> -		VMW_DEBUG_USER("SM4 surface not supported.\n");
> -		return -EINVAL;
> +	if (req->base.array_size > 0) {
> +		if (has_sm5_context(dev_priv)) {
> +			if (req->base.array_size > SVGA3D_SM5_MAX_SURFACE_ARRAYSIZE) {
> +				VMW_DEBUG_USER("Invalid Surface Array Size.\n");
> +				return -EINVAL;
> +			}
> +		} else if (has_sm4_context(dev_priv)) {
> +			if (req->base.array_size > SVGA3D_SM4_MAX_SURFACE_ARRAYSIZE) {
> +				VMW_DEBUG_USER("Invalid Surface Array Size.\n");
> +				return -EINVAL;
> +			}
> +		} else {
> +			VMW_DEBUG_USER("SM4+ surface not supported.\n");
> +			return -EINVAL;
> +		}
>  	}
>  
>  	if (!has_sm4_1_context(dev_priv)) {

LGTM!

Reviewed-by: Maaz Mombasawala <maaz.mombasawala@broadcom.com>

-- 
Maaz Mombasawala <maaz.mombasawala@broadcom.com>

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-07-01 18:27 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-23 19:33 [PATCH] drm/vmwgfx: Validate vmw_surface_metadata::array_size Ian Forbes
2026-06-23 21:22 ` sashiko-bot
2026-07-01 18:31 ` Maaz Mombasawala

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.