aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/firewire/core-device.c32
1 files changed, 22 insertions, 10 deletions
diff --git a/drivers/firewire/core-device.c b/drivers/firewire/core-device.c
index eecd52dc8e98..e02bf2dff845 100644
--- a/drivers/firewire/core-device.c
+++ b/drivers/firewire/core-device.c
@@ -18,6 +18,7 @@
18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */ 19 */
20 20
21#include <linux/bug.h>
21#include <linux/ctype.h> 22#include <linux/ctype.h>
22#include <linux/delay.h> 23#include <linux/delay.h>
23#include <linux/device.h> 24#include <linux/device.h>
@@ -580,11 +581,7 @@ static int read_bus_info_block(struct fw_device *device, int generation)
580 */ 581 */
581 key = stack[--sp]; 582 key = stack[--sp];
582 i = key & 0xffffff; 583 i = key & 0xffffff;
583 if (i >= READ_BIB_ROM_SIZE) 584 if (WARN_ON(i >= READ_BIB_ROM_SIZE))
584 /*
585 * The reference points outside the standard
586 * config rom area, something's fishy.
587 */
588 goto out; 585 goto out;
589 586
590 /* Read header quadlet for the block to get the length. */ 587 /* Read header quadlet for the block to get the length. */
@@ -606,14 +603,29 @@ static int read_bus_info_block(struct fw_device *device, int generation)
606 * block, check the entries as we read them to see if 603 * block, check the entries as we read them to see if
607 * it references another block, and push it in that case. 604 * it references another block, and push it in that case.
608 */ 605 */
609 while (i < end) { 606 for (; i < end; i++) {
610 if (read_rom(device, generation, i, &rom[i]) != 607 if (read_rom(device, generation, i, &rom[i]) !=
611 RCODE_COMPLETE) 608 RCODE_COMPLETE)
612 goto out; 609 goto out;
613 if ((key >> 30) == 3 && (rom[i] >> 30) > 1 && 610
614 sp < READ_BIB_STACK_SIZE) 611 if ((key >> 30) != 3 || (rom[i] >> 30) < 2 ||
615 stack[sp++] = i + rom[i]; 612 sp >= READ_BIB_STACK_SIZE)
616 i++; 613 continue;
614 /*
615 * Offset points outside the ROM. May be a firmware
616 * bug or an Extended ROM entry (IEEE 1212-2001 clause
617 * 7.7.18). Simply overwrite this pointer here by a
618 * fake immediate entry so that later iterators over
619 * the ROM don't have to check offsets all the time.
620 */
621 if (i + (rom[i] & 0xffffff) >= READ_BIB_ROM_SIZE) {
622 fw_error("skipped unsupported ROM entry %x at %llx\n",
623 rom[i],
624 i * 4 | CSR_REGISTER_BASE | CSR_CONFIG_ROM);
625 rom[i] = 0;
626 continue;
627 }
628 stack[sp++] = i + rom[i];
617 } 629 }
618 if (length < i) 630 if (length < i)
619 length = i; 631 length = i;