diff options
author | Michael Chan <mchan@broadcom.com> | 2006-11-20 00:12:55 +0100 |
---|---|---|
committer | Adrian Bunk <bunk@stusta.de> | 2006-11-20 00:12:55 +0100 |
commit | 9d41b6ad6669529146a588fae30af28ab4443450 (patch) | |
tree | f8c29f558e31effad37e061ebe01ac5b59ca5f26 | |
parent | de6c0ccfa9ab24a9104c8791030e8ebecb1e2c5a (diff) |
[TG3]: Fix array overrun in tg3_read_partno().
Use proper upper limits for the loops and check for all error
conditions.
The problem was noticed by Adrian Bunk.
Signed-off-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: Adrian Bunk <bunk@stusta.de>
-rw-r--r-- | drivers/net/tg3.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 7d007221ceb..6d638361d1a 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -9344,7 +9344,7 @@ skip_phy_reset: static void __devinit tg3_read_partno(struct tg3 *tp) { unsigned char vpd_data[256]; - int i; + unsigned int i; if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) { /* Sun decided not to put the necessary bits in the @@ -9367,9 +9367,9 @@ static void __devinit tg3_read_partno(struct tg3 *tp) } /* Now parse and find the part number. */ - for (i = 0; i < 256; ) { + for (i = 0; i < 254; ) { unsigned char val = vpd_data[i]; - int block_end; + unsigned int block_end; if (val == 0x82 || val == 0x91) { i = (i + 3 + @@ -9385,21 +9385,26 @@ static void __devinit tg3_read_partno(struct tg3 *tp) (vpd_data[i + 1] + (vpd_data[i + 2] << 8))); i += 3; - while (i < block_end) { + + if (block_end > 256) + goto out_not_found; + + while (i < (block_end - 2)) { if (vpd_data[i + 0] == 'P' && vpd_data[i + 1] == 'N') { int partno_len = vpd_data[i + 2]; - if (partno_len > 24) + i += 3; + if (partno_len > 24 || (partno_len + i) > 256) goto out_not_found; memcpy(tp->board_part_number, - &vpd_data[i + 3], - partno_len); + &vpd_data[i], partno_len); /* Success. */ return; } + i += 3 + vpd_data[i + 2]; } /* Part number not found. */ |