sb/amd/sr5650: Add fine-grained bounds checking

The code currently checks that 4 <= dev_index <= 10, which after
subtraction by 4 can index into an array of length at most 7. This is
fine for the largest cpl array (which does have length 7), but is
too large for some of the others, which are smaller. This adds bounds
checks for each array access to ensure they are all within bounds.

Change-Id: I1610d35ca6cbb6cfb42c251e75b0e8b22b64252b
Signed-off-by: Jacob Garber <jgarber1@ualberta.ca>
Found-by: Coverity CID 1229676
Reviewed-on: https://review.coreboot.org/c/coreboot/+/33458
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: HAOUAS Elyes <ehaouas@noos.fr>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
Jacob Garber 2019-06-13 15:34:55 -06:00 committed by Martin Roth
parent 1557a67c83
commit 715d60abce
1 changed files with 22 additions and 10 deletions

View File

@ -360,41 +360,53 @@ const u8 pGpp111111[] = {0x0E, 0x0E, 0x0E, 0x0E, 0, 0x0E, 0x0E};
static void gpp3a_cpl_buf_alloc(struct device *nb_dev, struct device *dev) static void gpp3a_cpl_buf_alloc(struct device *nb_dev, struct device *dev)
{ {
u8 dev_index; u8 dev_index;
u8 *slave_cpl;
u8 value; u8 value;
struct southbridge_amd_sr5650_config *cfg = struct southbridge_amd_sr5650_config *cfg =
(struct southbridge_amd_sr5650_config *)nb_dev->chip_info; (struct southbridge_amd_sr5650_config *)nb_dev->chip_info;
dev_index = dev->path.pci.devfn >> 3; dev_index = dev->path.pci.devfn >> 3;
if (dev_index < 4 || dev_index > 0xa) {
if (dev_index < 4)
return; return;
}
dev_index -= 4;
switch (cfg->gpp3a_configuration) { switch (cfg->gpp3a_configuration) {
case 0x1: /* 4:2:0:0:0:0 */ case 0x1: /* 4:2:0:0:0:0 */
slave_cpl = (u8 *)&pGpp420000; if (dev_index >= ARRAY_SIZE(pGpp420000))
return;
value = pGpp420000[dev_index];
break; break;
case 0x2: /* 4:1:1:0:0:0 */ case 0x2: /* 4:1:1:0:0:0 */
slave_cpl = (u8 *)&pGpp411000; if (dev_index >= ARRAY_SIZE(pGpp411000))
return;
value = pGpp411000[dev_index];
break; break;
case 0xC: /* 2:2:2:0:0:0 */ case 0xC: /* 2:2:2:0:0:0 */
slave_cpl = (u8 *)&pGpp222000; if (dev_index >= ARRAY_SIZE(pGpp222000))
return;
value = pGpp222000[dev_index];
break; break;
case 0xA: /* 2:2:1:1:0:0 */ case 0xA: /* 2:2:1:1:0:0 */
slave_cpl = (u8 *)&pGpp221100; if (dev_index >= ARRAY_SIZE(pGpp221100))
return;
value = pGpp221100[dev_index];
break; break;
case 0x4: /* 2:1:1:1:1:0 */ case 0x4: /* 2:1:1:1:1:0 */
slave_cpl = (u8 *)&pGpp211110; if (dev_index >= ARRAY_SIZE(pGpp211110))
return;
value = pGpp211110[dev_index];
break; break;
case 0xB: /* 1:1:1:1:1:1 */ case 0xB: /* 1:1:1:1:1:1 */
slave_cpl = (u8 *)&pGpp111111; if (dev_index >= ARRAY_SIZE(pGpp111111))
return;
value = pGpp111111[dev_index];
break; break;
default: /* shouldn't be here. */ default: /* shouldn't be here. */
printk(BIOS_WARNING, "buggy gpp3a_configuration\n"); printk(BIOS_WARNING, "buggy gpp3a_configuration\n");
return; return;
} }
value = slave_cpl[dev_index - 4];
if (value != 0) { if (value != 0) {
set_pcie_enable_bits(dev, 0x10, 0x3f << 8, value << 8); set_pcie_enable_bits(dev, 0x10, 0x3f << 8, value << 8);
set_pcie_enable_bits(dev, 0x20, 1 << 11, 1 << 11); set_pcie_enable_bits(dev, 0x20, 1 << 11, 1 << 11);