diff options
| author | Michel Daenzer <michel@tungstengraphics.com> | 2006-09-21 14:12:11 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@linux.ie> | 2006-09-21 15:32:34 -0400 |
| commit | 214ff13d9ebbba7940f29bc89669f85f12533083 (patch) | |
| tree | bb1e106de12fca7046be3bc6b21cb13a765e4ea1 | |
| parent | 47cc140931cc03076014fdbfdd512d6dd9d74d34 (diff) | |
drm: fd.o Bug #7595: Avoid u32 overflows in radeon_check_and_fixup_offset().
The overflows could cause valid offsets to get rejected under some
circumstances, e.g. when the framebuffer resides at the very end of the card's
address space.
Signed-off-by: Dave Airlie <airlied@linux.ie>
| -rw-r--r-- | drivers/char/drm/radeon_state.c | 25 |
1 files changed, 12 insertions, 13 deletions
diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 0433ff80cb70..bcfa1514a4d0 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c | |||
| @@ -42,7 +42,11 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * | |||
| 42 | drm_file_t * filp_priv, | 42 | drm_file_t * filp_priv, |
| 43 | u32 *offset) | 43 | u32 *offset) |
| 44 | { | 44 | { |
| 45 | u32 off = *offset; | 45 | u64 off = *offset; |
| 46 | u32 fb_start = dev_priv->fb_location; | ||
| 47 | u32 fb_end = fb_start + dev_priv->fb_size - 1; | ||
| 48 | u32 gart_start = dev_priv->gart_vm_start; | ||
| 49 | u32 gart_end = gart_start + dev_priv->gart_size - 1; | ||
| 46 | struct drm_radeon_driver_file_fields *radeon_priv; | 50 | struct drm_radeon_driver_file_fields *radeon_priv; |
| 47 | 51 | ||
| 48 | /* Hrm ... the story of the offset ... So this function converts | 52 | /* Hrm ... the story of the offset ... So this function converts |
| @@ -62,10 +66,8 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * | |||
| 62 | /* First, the best case, the offset already lands in either the | 66 | /* First, the best case, the offset already lands in either the |
| 63 | * framebuffer or the GART mapped space | 67 | * framebuffer or the GART mapped space |
| 64 | */ | 68 | */ |
| 65 | if ((off >= dev_priv->fb_location && | 69 | if ((off >= fb_start && off <= fb_end) || |
| 66 | off < (dev_priv->fb_location + dev_priv->fb_size)) || | 70 | (off >= gart_start && off <= gart_end)) |
| 67 | (off >= dev_priv->gart_vm_start && | ||
| 68 | off < (dev_priv->gart_vm_start + dev_priv->gart_size))) | ||
| 69 | return 0; | 71 | return 0; |
| 70 | 72 | ||
| 71 | /* Ok, that didn't happen... now check if we have a zero based | 73 | /* Ok, that didn't happen... now check if we have a zero based |
| @@ -78,16 +80,13 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * | |||
| 78 | } | 80 | } |
| 79 | 81 | ||
| 80 | /* Finally, assume we aimed at a GART offset if beyond the fb */ | 82 | /* Finally, assume we aimed at a GART offset if beyond the fb */ |
| 81 | if (off > (dev_priv->fb_location + dev_priv->fb_size)) | 83 | if (off > fb_end) |
| 82 | off = off - (dev_priv->fb_location + dev_priv->fb_size) + | 84 | off = off - fb_end - 1 + gart_start; |
| 83 | dev_priv->gart_vm_start; | ||
| 84 | 85 | ||
| 85 | /* Now recheck and fail if out of bounds */ | 86 | /* Now recheck and fail if out of bounds */ |
| 86 | if ((off >= dev_priv->fb_location && | 87 | if ((off >= fb_start && off <= fb_end) || |
| 87 | off < (dev_priv->fb_location + dev_priv->fb_size)) || | 88 | (off >= gart_start && off <= gart_end)) { |
| 88 | (off >= dev_priv->gart_vm_start && | 89 | DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off); |
| 89 | off < (dev_priv->gart_vm_start + dev_priv->gart_size))) { | ||
| 90 | DRM_DEBUG("offset fixed up to 0x%x\n", off); | ||
| 91 | *offset = off; | 90 | *offset = off; |
| 92 | return 0; | 91 | return 0; |
| 93 | } | 92 | } |
