aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Chan <mchan@broadcom.com>2006-11-20 00:12:55 +0100
committerAdrian Bunk <bunk@stusta.de>2006-11-20 00:12:55 +0100
commit9d41b6ad6669529146a588fae30af28ab4443450 (patch)
treef8c29f558e31effad37e061ebe01ac5b59ca5f26
parentde6c0ccfa9ab24a9104c8791030e8ebecb1e2c5a (diff)
downloadlinux-linaro-stable-9d41b6ad6669529146a588fae30af28ab4443450.tar.gz
[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.c19
1 files changed, 12 insertions, 7 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c
index 7d007221cebb..6d638361d1a5 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. */