aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajesh K Borundia <rajesh.borundia@qlogic.com>2010-03-28 22:43:43 -0400
committerDavid S. Miller <davem@davemloft.net>2010-03-29 16:18:37 -0400
commit10c0f2a852a529eacf2f223bbaef47832224a521 (patch)
treed2f2c6cca67ad3a8c8526d2bb707b99639cf93f5
parent6b50ea1516fab30ce5843e5b11e43488f38c776d (diff)
netxen: validate unified romimage
Signed-off-by: Rajesh K Borundia <rajesh.borundia@qlogic.com> Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com> Validate all sections of unified romimage, before accessing them, to avoid seg fault. Signed-off-by: Amit Kumar Salecha <amit.salecha@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/netxen/netxen_nic.h1
-rw-r--r--drivers/net/netxen/netxen_nic_init.c154
2 files changed, 140 insertions, 15 deletions
diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h
index 144d2e880422..33ae5e13b608 100644
--- a/drivers/net/netxen/netxen_nic.h
+++ b/drivers/net/netxen/netxen_nic.h
@@ -420,7 +420,6 @@ struct status_desc {
420} __attribute__ ((aligned(16))); 420} __attribute__ ((aligned(16)));
421 421
422/* UNIFIED ROMIMAGE *************************/ 422/* UNIFIED ROMIMAGE *************************/
423#define NX_UNI_FW_MIN_SIZE 0xc8000
424#define NX_UNI_DIR_SECT_PRODUCT_TBL 0x0 423#define NX_UNI_DIR_SECT_PRODUCT_TBL 0x0
425#define NX_UNI_DIR_SECT_BOOTLD 0x6 424#define NX_UNI_DIR_SECT_BOOTLD 0x6
426#define NX_UNI_DIR_SECT_FW 0x7 425#define NX_UNI_DIR_SECT_FW 0x7
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 1c63610ead42..141bc4389fec 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -613,22 +613,123 @@ static struct uni_table_desc *nx_get_table_desc(const u8 *unirom, int section)
613 return NULL; 613 return NULL;
614} 614}
615 615
616#define QLCNIC_FILEHEADER_SIZE (14 * 4)
617
616static int 618static int
617nx_set_product_offs(struct netxen_adapter *adapter) 619netxen_nic_validate_header(struct netxen_adapter *adapter)
618{ 620 {
619 struct uni_table_desc *ptab_descr;
620 const u8 *unirom = adapter->fw->data; 621 const u8 *unirom = adapter->fw->data;
621 uint32_t i; 622 struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0];
623 u32 fw_file_size = adapter->fw->size;
624 u32 tab_size;
622 __le32 entries; 625 __le32 entries;
626 __le32 entry_size;
627
628 if (fw_file_size < QLCNIC_FILEHEADER_SIZE)
629 return -EINVAL;
630
631 entries = cpu_to_le32(directory->num_entries);
632 entry_size = cpu_to_le32(directory->entry_size);
633 tab_size = cpu_to_le32(directory->findex) + (entries * entry_size);
634
635 if (fw_file_size < tab_size)
636 return -EINVAL;
637
638 return 0;
639}
640
641static int
642netxen_nic_validate_bootld(struct netxen_adapter *adapter)
643{
644 struct uni_table_desc *tab_desc;
645 struct uni_data_desc *descr;
646 const u8 *unirom = adapter->fw->data;
647 __le32 idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
648 NX_UNI_BOOTLD_IDX_OFF));
649 u32 offs;
650 u32 tab_size;
651 u32 data_size;
652
653 tab_desc = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_BOOTLD);
654
655 if (!tab_desc)
656 return -EINVAL;
623 657
658 tab_size = cpu_to_le32(tab_desc->findex) +
659 (cpu_to_le32(tab_desc->entry_size) * (idx + 1));
660
661 if (adapter->fw->size < tab_size)
662 return -EINVAL;
663
664 offs = cpu_to_le32(tab_desc->findex) +
665 (cpu_to_le32(tab_desc->entry_size) * (idx));
666 descr = (struct uni_data_desc *)&unirom[offs];
667
668 data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
669
670 if (adapter->fw->size < data_size)
671 return -EINVAL;
672
673 return 0;
674}
675
676static int
677netxen_nic_validate_fw(struct netxen_adapter *adapter)
678{
679 struct uni_table_desc *tab_desc;
680 struct uni_data_desc *descr;
681 const u8 *unirom = adapter->fw->data;
682 __le32 idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] +
683 NX_UNI_FIRMWARE_IDX_OFF));
684 u32 offs;
685 u32 tab_size;
686 u32 data_size;
687
688 tab_desc = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_FW);
689
690 if (!tab_desc)
691 return -EINVAL;
692
693 tab_size = cpu_to_le32(tab_desc->findex) +
694 (cpu_to_le32(tab_desc->entry_size) * (idx + 1));
695
696 if (adapter->fw->size < tab_size)
697 return -EINVAL;
698
699 offs = cpu_to_le32(tab_desc->findex) +
700 (cpu_to_le32(tab_desc->entry_size) * (idx));
701 descr = (struct uni_data_desc *)&unirom[offs];
702 data_size = cpu_to_le32(descr->findex) + cpu_to_le32(descr->size);
703
704 if (adapter->fw->size < data_size)
705 return -EINVAL;
706
707 return 0;
708}
709
710
711static int
712netxen_nic_validate_product_offs(struct netxen_adapter *adapter)
713{
714 struct uni_table_desc *ptab_descr;
715 const u8 *unirom = adapter->fw->data;
624 int mn_present = (NX_IS_REVISION_P2(adapter->ahw.revision_id)) ? 716 int mn_present = (NX_IS_REVISION_P2(adapter->ahw.revision_id)) ?
625 1 : netxen_p3_has_mn(adapter); 717 1 : netxen_p3_has_mn(adapter);
718 __le32 entries;
719 __le32 entry_size;
720 u32 tab_size;
721 u32 i;
626 722
627 ptab_descr = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_PRODUCT_TBL); 723 ptab_descr = nx_get_table_desc(unirom, NX_UNI_DIR_SECT_PRODUCT_TBL);
628 if (ptab_descr == NULL) 724 if (ptab_descr == NULL)
629 return -1; 725 return -EINVAL;
630 726
631 entries = cpu_to_le32(ptab_descr->num_entries); 727 entries = cpu_to_le32(ptab_descr->num_entries);
728 entry_size = cpu_to_le32(ptab_descr->entry_size);
729 tab_size = cpu_to_le32(ptab_descr->findex) + (entries * entry_size);
730
731 if (adapter->fw->size < tab_size)
732 return -EINVAL;
632 733
633nomn: 734nomn:
634 for (i = 0; i < entries; i++) { 735 for (i = 0; i < entries; i++) {
@@ -657,9 +758,38 @@ nomn:
657 goto nomn; 758 goto nomn;
658 } 759 }
659 760
660 return -1; 761 return -EINVAL;
661} 762}
662 763
764static int
765netxen_nic_validate_unified_romimage(struct netxen_adapter *adapter)
766{
767 if (netxen_nic_validate_header(adapter)) {
768 dev_err(&adapter->pdev->dev,
769 "unified image: header validation failed\n");
770 return -EINVAL;
771 }
772
773 if (netxen_nic_validate_product_offs(adapter)) {
774 dev_err(&adapter->pdev->dev,
775 "unified image: product validation failed\n");
776 return -EINVAL;
777 }
778
779 if (netxen_nic_validate_bootld(adapter)) {
780 dev_err(&adapter->pdev->dev,
781 "unified image: bootld validation failed\n");
782 return -EINVAL;
783 }
784
785 if (netxen_nic_validate_fw(adapter)) {
786 dev_err(&adapter->pdev->dev,
787 "unified image: firmware validation failed\n");
788 return -EINVAL;
789 }
790
791 return 0;
792}
663 793
664static struct uni_data_desc *nx_get_data_desc(struct netxen_adapter *adapter, 794static struct uni_data_desc *nx_get_data_desc(struct netxen_adapter *adapter,
665 u32 section, u32 idx_offset) 795 u32 section, u32 idx_offset)
@@ -933,27 +1063,23 @@ static int
933netxen_validate_firmware(struct netxen_adapter *adapter) 1063netxen_validate_firmware(struct netxen_adapter *adapter)
934{ 1064{
935 __le32 val; 1065 __le32 val;
936 u32 ver, min_ver, bios, min_size; 1066 u32 ver, min_ver, bios;
937 struct pci_dev *pdev = adapter->pdev; 1067 struct pci_dev *pdev = adapter->pdev;
938 const struct firmware *fw = adapter->fw; 1068 const struct firmware *fw = adapter->fw;
939 u8 fw_type = adapter->fw_type; 1069 u8 fw_type = adapter->fw_type;
940 1070
941 if (fw_type == NX_UNIFIED_ROMIMAGE) { 1071 if (fw_type == NX_UNIFIED_ROMIMAGE) {
942 if (nx_set_product_offs(adapter)) 1072 if (netxen_nic_validate_unified_romimage(adapter))
943 return -EINVAL; 1073 return -EINVAL;
944
945 min_size = NX_UNI_FW_MIN_SIZE;
946 } else { 1074 } else {
947 val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]); 1075 val = cpu_to_le32(*(u32 *)&fw->data[NX_FW_MAGIC_OFFSET]);
948 if ((__force u32)val != NETXEN_BDINFO_MAGIC) 1076 if ((__force u32)val != NETXEN_BDINFO_MAGIC)
949 return -EINVAL; 1077 return -EINVAL;
950 1078
951 min_size = NX_FW_MIN_SIZE; 1079 if (fw->size < NX_FW_MIN_SIZE)
1080 return -EINVAL;
952 } 1081 }
953 1082
954 if (fw->size < min_size)
955 return -EINVAL;
956
957 val = nx_get_fw_version(adapter); 1083 val = nx_get_fw_version(adapter);
958 1084
959 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) 1085 if (NX_IS_REVISION_P3(adapter->ahw.revision_id))