aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaro Koskinen <aaro.koskinen@iki.fi>2011-12-05 17:10:40 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2011-12-08 15:26:06 -0500
commit08ce239c106f1d147820f419e3dde86422663e7f (patch)
treef9bf0d4027ba680cb5761966ffa79194ae74bb11
parent82986dd9e738996a9d2e508c164d1eb7464c07c6 (diff)
staging: xgifb: ReadVBIOSTablData(): check the BIOS size
Check the BIOS size to avoid out of bounds array access. Disable LVDS in case errors are detected. Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/staging/xgifb/vb_init.c28
1 files changed, 21 insertions, 7 deletions
diff --git a/drivers/staging/xgifb/vb_init.c b/drivers/staging/xgifb/vb_init.c
index b4383948d72a..96e2334af2a1 100644
--- a/drivers/staging/xgifb/vb_init.c
+++ b/drivers/staging/xgifb/vb_init.c
@@ -1093,13 +1093,12 @@ static void XGINew_SetDRAMSize_340(struct xgi_hw_device_info *HwDeviceExtension,
1093 xgifb_reg_set(pVBInfo->P3c4, 0x21, (unsigned short) (data | 0x20)); 1093 xgifb_reg_set(pVBInfo->P3c4, 0x21, (unsigned short) (data | 0x20));
1094} 1094}
1095 1095
1096static u8 *xgifb_copy_rom(struct pci_dev *dev) 1096static u8 *xgifb_copy_rom(struct pci_dev *dev, size_t *rom_size)
1097{ 1097{
1098 void __iomem *rom_address; 1098 void __iomem *rom_address;
1099 u8 *rom_copy; 1099 u8 *rom_copy;
1100 size_t rom_size;
1101 1100
1102 rom_address = pci_map_rom(dev, &rom_size); 1101 rom_address = pci_map_rom(dev, rom_size);
1103 if (rom_address == NULL) 1102 if (rom_address == NULL)
1104 return NULL; 1103 return NULL;
1105 1104
@@ -1107,8 +1106,8 @@ static u8 *xgifb_copy_rom(struct pci_dev *dev)
1107 if (rom_copy == NULL) 1106 if (rom_copy == NULL)
1108 goto done; 1107 goto done;
1109 1108
1110 rom_size = min_t(size_t, rom_size, XGIFB_ROM_SIZE); 1109 *rom_size = min_t(size_t, *rom_size, XGIFB_ROM_SIZE);
1111 memcpy_fromio(rom_copy, rom_address, rom_size); 1110 memcpy_fromio(rom_copy, rom_address, *rom_size);
1112 1111
1113done: 1112done:
1114 pci_unmap_rom(dev, rom_address); 1113 pci_unmap_rom(dev, rom_address);
@@ -1123,27 +1122,37 @@ static void ReadVBIOSTablData(struct pci_dev *pdev,
1123 unsigned long i; 1122 unsigned long i;
1124 unsigned char j, k; 1123 unsigned char j, k;
1125 struct XGI21_LVDSCapStruct *lvds; 1124 struct XGI21_LVDSCapStruct *lvds;
1125 size_t vbios_size;
1126 1126
1127 if (xgifb_info->chip != XG21) 1127 if (xgifb_info->chip != XG21)
1128 return; 1128 return;
1129 pVBInfo->IF_DEF_LVDS = 0; 1129 pVBInfo->IF_DEF_LVDS = 0;
1130 vbios = xgifb_copy_rom(pdev); 1130 vbios = xgifb_copy_rom(pdev, &vbios_size);
1131 if (vbios == NULL) { 1131 if (vbios == NULL) {
1132 dev_err(&pdev->dev, "video BIOS not available\n"); 1132 dev_err(&pdev->dev, "video BIOS not available\n");
1133 return; 1133 return;
1134 } 1134 }
1135 if (vbios_size <= 0x65)
1136 goto error;
1135 if (!(vbios[0x65] & 0x1)) { 1137 if (!(vbios[0x65] & 0x1)) {
1136 vfree(vbios); 1138 vfree(vbios);
1137 return; 1139 return;
1138 } 1140 }
1139 pVBInfo->IF_DEF_LVDS = 1; 1141 if (vbios_size <= 0x317)
1142 goto error;
1140 i = vbios[0x316] | (vbios[0x317] << 8); 1143 i = vbios[0x316] | (vbios[0x317] << 8);
1144 if (vbios_size <= i - 1)
1145 goto error;
1141 j = vbios[i - 1]; 1146 j = vbios[i - 1];
1147 if (j == 0)
1148 goto error;
1142 if (j == 0xff) 1149 if (j == 0xff)
1143 j = 1; 1150 j = 1;
1144 k = 0; 1151 k = 0;
1145 lvds = &pVBInfo->XG21_LVDSCapList[0]; 1152 lvds = &pVBInfo->XG21_LVDSCapList[0];
1146 do { 1153 do {
1154 if (vbios_size <= i + 24)
1155 goto error;
1147 lvds->LVDS_Capability = vbios[i] | (vbios[i + 1] << 8); 1156 lvds->LVDS_Capability = vbios[i] | (vbios[i + 1] << 8);
1148 lvds->LVDSHT = vbios[i + 2] | (vbios[i + 3] << 8); 1157 lvds->LVDSHT = vbios[i + 2] | (vbios[i + 3] << 8);
1149 lvds->LVDSVT = vbios[i + 4] | (vbios[i + 5] << 8); 1158 lvds->LVDSVT = vbios[i + 4] | (vbios[i + 5] << 8);
@@ -1166,6 +1175,11 @@ static void ReadVBIOSTablData(struct pci_dev *pdev,
1166 lvds++; 1175 lvds++;
1167 } while (j > 0 && k < ARRAY_SIZE(XGI21_LCDCapList)); 1176 } while (j > 0 && k < ARRAY_SIZE(XGI21_LCDCapList));
1168 vfree(vbios); 1177 vfree(vbios);
1178 pVBInfo->IF_DEF_LVDS = 1;
1179 return;
1180error:
1181 dev_err(&pdev->dev, "video BIOS corrupted\n");
1182 vfree(vbios);
1169} 1183}
1170 1184
1171static void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension, 1185static void XGINew_ChkSenseStatus(struct xgi_hw_device_info *HwDeviceExtension,