mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
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: 8e911ab770 ("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>
This commit is contained in:
parent
ad0150fa2f
commit
fc3659f178
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user