diff options
| author | Werner Kasselman <werner@verivus.ai> | 2026-04-14 05:08:42 +0000 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2026-04-17 15:41:13 -0400 |
| commit | fc3659f178d4a65599167d5a648bbeef4b0d4446 (patch) | |
| tree | 427ecede5edc36615115f8fd2666aa03d202acb5 /drivers | |
| parent | ad0150fa2fade906b1dfcbb1895037e5f39d9561 (diff) | |
| download | linux-fc3659f178d4a65599167d5a648bbeef4b0d4446.tar.gz linux-fc3659f178d4a65599167d5a648bbeef4b0d4446.zip | |
drm/amdgpu: fix integer overflow in amdgpu_gem_align_pitch()
amdgpu_gem_align_pitch() is passed u32 width and cpp from dumb buffer
creation but uses signed int internally. The round-up add and the
aligned * cpp multiplication can overflow, returning zero or a negative
pitch. A zero pitch propagates to a zero-sized GEM object allocation
that reaches userspace via DRM_IOCTL_MODE_CREATE_DUMB.
Switch the helper to unsigned int and use check_add_overflow() /
check_mul_overflow() so wraparound returns zero. Reject a zero pitch
or size in amdgpu_mode_dumb_create() rather than allocating a zero-
byte BO.
Fixes: 8e911ab770f7 ("drm: amdgpu: Replace drm_fb_get_bpp_depth() with drm_format_plane_cpp()")
Signed-off-by: Werner Kasselman <werner@verivus.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 25 |
1 files changed, 17 insertions, 8 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 5376035d32fe..9ef80bca4102 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -27,6 +27,7 @@ */ #include <linux/ktime.h> #include <linux/module.h> +#include <linux/overflow.h> #include <linux/pagemap.h> #include <linux/pci.h> #include <linux/dma-buf.h> @@ -1217,13 +1218,14 @@ int amdgpu_gem_list_handles_ioctl(struct drm_device *dev, void *data, return ret; } -static int amdgpu_gem_align_pitch(struct amdgpu_device *adev, - int width, - int cpp, - bool tiled) +static unsigned int amdgpu_gem_align_pitch(struct amdgpu_device *adev, + unsigned int width, + unsigned int cpp, + bool tiled) { - int aligned = width; - int pitch_mask = 0; + unsigned int aligned = width; + unsigned int pitch_mask = 0; + unsigned int pitch; switch (cpp) { case 1: @@ -1238,9 +1240,12 @@ static int amdgpu_gem_align_pitch(struct amdgpu_device *adev, break; } - aligned += pitch_mask; + if (check_add_overflow(aligned, pitch_mask, &aligned)) + return 0; aligned &= ~pitch_mask; - return aligned * cpp; + if (check_mul_overflow(aligned, cpp, &pitch)) + return 0; + return pitch; } int amdgpu_mode_dumb_create(struct drm_file *file_priv, @@ -1267,8 +1272,12 @@ int amdgpu_mode_dumb_create(struct drm_file *file_priv, args->pitch = amdgpu_gem_align_pitch(adev, args->width, DIV_ROUND_UP(args->bpp, 8), 0); + if (!args->pitch) + return -EINVAL; args->size = (u64)args->pitch * args->height; args->size = ALIGN(args->size, PAGE_SIZE); + if (!args->size) + return -EINVAL; domain = amdgpu_bo_get_preferred_domain(adev, amdgpu_display_supported_domains(adev, flags)); r = amdgpu_gem_object_create(adev, args->size, 0, domain, flags, |
