CVE-2010-5331: Off-by-one Error (CWE-193)
value: In the Linux kernel before 2.6.34, a range check issue in drivers/gpu/drm/radeon/atombios.c could cause an off by one (buffer overflow) problem. NOTE: At least one Linux maintainer believes that this CVE is incorrectly assigned and should be rejected because the value is hard coded and are not user-controllable where it is used
CWE description: A product calculates or uses an incorrect maximum or minimum value that is 1 more, or 1 less, than the correct value.
CVSS v3 base score: 7.8
Published: 2019-07-27T22:15Z
Repository: https://github.com/torvalds/linux
Language: C
Files changed: drivers/gpu/drm/radeon/atombios.h, drivers/gpu/drm/radeon/radeon_atombios.c
Commit date: 2010-04-28 18:41:54 +1000
Commit message: drivers/gpu/drm/radeon/radeon_atombios.c: range check issues

This change makes the array larger, "MAX_SUPPORTED_TV_TIMING_V1_2" is 3
and the original size "MAX_SUPPORTED_TV_TIMING" is 2.

Also there were checks that were off by one.

Signed-off-by: Dan Carpenter <error27@gmail.com>
Acked-by: Alex Deucher <alexdeucher@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Dave Airlie <airlied@redhat.com>

Diff: diff --git a/drivers/gpu/drm/radeon/atombios.h b/drivers/gpu/drm/radeon/atombios.h
index 6732b5dd8ff4..27e2c715be11 100644
--- a/drivers/gpu/drm/radeon/atombios.h
+++ b/drivers/gpu/drm/radeon/atombios.h
@@ -2910,11 +2910,11 @@ typedef struct _ATOM_ANALOG_TV_INFO_V1_2
   ATOM_COMMON_TABLE_HEADER sHeader;  
   UCHAR                    ucTV_SupportedStandard;
   UCHAR                    ucTV_BootUpDefaultStandard; 
   UCHAR                    ucExt_TV_ASIC_ID;
   UCHAR                    ucExt_TV_ASIC_SlaveAddr;
-  ATOM_DTD_FORMAT          aModeTimings[MAX_SUPPORTED_TV_TIMING];
+  ATOM_DTD_FORMAT          aModeTimings[MAX_SUPPORTED_TV_TIMING_V1_2];
 }ATOM_ANALOG_TV_INFO_V1_2;
 
 typedef struct _ATOM_DPCD_INFO
 {
   UCHAR   ucRevisionNumber;        //10h : Revision 1.0; 11h : Revision 1.1   
diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c
index 5673665ff216..9916d825401c 100644
--- a/drivers/gpu/drm/radeon/radeon_atombios.c
+++ b/drivers/gpu/drm/radeon/radeon_atombios.c
@@ -1262,11 +1262,11 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
 		return false;
 
 	switch (crev) {
 	case 1:
 		tv_info = (ATOM_ANALOG_TV_INFO *)(mode_info->atom_context->bios + data_offset);
-		if (index > MAX_SUPPORTED_TV_TIMING)
+		if (index >= MAX_SUPPORTED_TV_TIMING)
 			return false;
 
 		mode->crtc_htotal = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Total);
 		mode->crtc_hdisplay = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_Disp);
 		mode->crtc_hsync_start = le16_to_cpu(tv_info->aModeTimings[index].usCRTC_H_SyncStart);
@@ -1300,11 +1300,11 @@ bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
 			mode->crtc_vtotal -= 1;
 		}
 		break;
 	case 2:
 		tv_info_v1_2 = (ATOM_ANALOG_TV_INFO_V1_2 *)(mode_info->atom_context->bios + data_offset);
-		if (index > MAX_SUPPORTED_TV_TIMING_V1_2)
+		if (index >= MAX_SUPPORTED_TV_TIMING_V1_2)
 			return false;
 
 		dtd_timings = &tv_info_v1_2->aModeTimings[index];
 		mode->crtc_htotal = le16_to_cpu(dtd_timings->usHActive) +
 			le16_to_cpu(dtd_timings->usHBlanking_Time);

Vulnerable code:   ATOM_DTD_FORMAT          aModeTimings[MAX_SUPPORTED_TV_TIMING];
		if (index > MAX_SUPPORTED_TV_TIMING)
		if (index > MAX_SUPPORTED_TV_TIMING_V1_2)
Fixed code:   ATOM_DTD_FORMAT          aModeTimings[MAX_SUPPORTED_TV_TIMING_V1_2];
		if (index >= MAX_SUPPORTED_TV_TIMING)
		if (index >= MAX_SUPPORTED_TV_TIMING_V1_2)