diff options
author | Michael Chan <mchan@broadcom.com> | 2006-11-07 17:57:51 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-11-07 18:10:16 -0500 |
commit | af2c6a4aaa2253f1e29df8fb59a3d92174d30a33 (patch) | |
tree | 5eb583eb426b70c342d7a5a0577b44564de70538 /drivers/net/tg3.c | |
parent | 25f484a62e41be8020b9a31bf50a792baa58d2d4 (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: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/tg3.c')
-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 8f059b7968bd..06e4f77b0988 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -10212,7 +10212,7 @@ skip_phy_reset: | |||
10212 | static void __devinit tg3_read_partno(struct tg3 *tp) | 10212 | static void __devinit tg3_read_partno(struct tg3 *tp) |
10213 | { | 10213 | { |
10214 | unsigned char vpd_data[256]; | 10214 | unsigned char vpd_data[256]; |
10215 | int i; | 10215 | unsigned int i; |
10216 | u32 magic; | 10216 | u32 magic; |
10217 | 10217 | ||
10218 | if (tg3_nvram_read_swab(tp, 0x0, &magic)) | 10218 | if (tg3_nvram_read_swab(tp, 0x0, &magic)) |
@@ -10258,9 +10258,9 @@ static void __devinit tg3_read_partno(struct tg3 *tp) | |||
10258 | } | 10258 | } |
10259 | 10259 | ||
10260 | /* Now parse and find the part number. */ | 10260 | /* Now parse and find the part number. */ |
10261 | for (i = 0; i < 256; ) { | 10261 | for (i = 0; i < 254; ) { |
10262 | unsigned char val = vpd_data[i]; | 10262 | unsigned char val = vpd_data[i]; |
10263 | int block_end; | 10263 | unsigned int block_end; |
10264 | 10264 | ||
10265 | if (val == 0x82 || val == 0x91) { | 10265 | if (val == 0x82 || val == 0x91) { |
10266 | i = (i + 3 + | 10266 | i = (i + 3 + |
@@ -10276,21 +10276,26 @@ static void __devinit tg3_read_partno(struct tg3 *tp) | |||
10276 | (vpd_data[i + 1] + | 10276 | (vpd_data[i + 1] + |
10277 | (vpd_data[i + 2] << 8))); | 10277 | (vpd_data[i + 2] << 8))); |
10278 | i += 3; | 10278 | i += 3; |
10279 | while (i < block_end) { | 10279 | |
10280 | if (block_end > 256) | ||
10281 | goto out_not_found; | ||
10282 | |||
10283 | while (i < (block_end - 2)) { | ||
10280 | if (vpd_data[i + 0] == 'P' && | 10284 | if (vpd_data[i + 0] == 'P' && |
10281 | vpd_data[i + 1] == 'N') { | 10285 | vpd_data[i + 1] == 'N') { |
10282 | int partno_len = vpd_data[i + 2]; | 10286 | int partno_len = vpd_data[i + 2]; |
10283 | 10287 | ||
10284 | if (partno_len > 24) | 10288 | i += 3; |
10289 | if (partno_len > 24 || (partno_len + i) > 256) | ||
10285 | goto out_not_found; | 10290 | goto out_not_found; |
10286 | 10291 | ||
10287 | memcpy(tp->board_part_number, | 10292 | memcpy(tp->board_part_number, |
10288 | &vpd_data[i + 3], | 10293 | &vpd_data[i], partno_len); |
10289 | partno_len); | ||
10290 | 10294 | ||
10291 | /* Success. */ | 10295 | /* Success. */ |
10292 | return; | 10296 | return; |
10293 | } | 10297 | } |
10298 | i += 3 + vpd_data[i + 2]; | ||
10294 | } | 10299 | } |
10295 | 10300 | ||
10296 | /* Part number not found. */ | 10301 | /* Part number not found. */ |