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 /drivers | |
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>
Diffstat (limited to 'drivers')
-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 | } |