aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/libertas
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2013-10-14 18:51:55 -0400
committerJohn W. Linville <linville@tuxdriver.com>2013-10-18 14:03:54 -0400
commit1dfba3060fe7ee03ccec25a91d35085142dfc295 (patch)
treec27da4ef59aeaa75b1d39c46af0aeed4f7ba7147 /drivers/net/wireless/libertas
parente07f01e4c7d583adb1ec25e63a52db5fc10a94d3 (diff)
libertas: move firmware lifetime handling to firmware.c
Previously, each bus type was responsible for freeing the firmware structure, but some did that badly. Move responsibility for freeing firmware into firmware.c so that it's done once and correctly, instead of happening in multiple places in bus-specific code. This fixes a use-after-free bug found by Dr. H. Nikolaus Schaller where the SDIO code forgot to NULL priv->helper_fw after freeing it. Signed-off-by: Dan Williams <dcbw@redhat.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/libertas')
-rw-r--r--drivers/net/wireless/libertas/firmware.c5
-rw-r--r--drivers/net/wireless/libertas/if_cs.c8
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c8
-rw-r--r--drivers/net/wireless/libertas/if_spi.c4
-rw-r--r--drivers/net/wireless/libertas/if_usb.c17
5 files changed, 16 insertions, 26 deletions
diff --git a/drivers/net/wireless/libertas/firmware.c b/drivers/net/wireless/libertas/firmware.c
index c0f9e7e862f6..51b92b5df119 100644
--- a/drivers/net/wireless/libertas/firmware.c
+++ b/drivers/net/wireless/libertas/firmware.c
@@ -53,6 +53,11 @@ static void main_firmware_cb(const struct firmware *firmware, void *context)
53 53
54 /* Firmware found! */ 54 /* Firmware found! */
55 lbs_fw_loaded(priv, 0, priv->helper_fw, firmware); 55 lbs_fw_loaded(priv, 0, priv->helper_fw, firmware);
56 if (priv->helper_fw) {
57 release_firmware (priv->helper_fw);
58 priv->helper_fw = NULL;
59 }
60 release_firmware (firmware);
56} 61}
57 62
58static void helper_firmware_cb(const struct firmware *firmware, void *context) 63static void helper_firmware_cb(const struct firmware *firmware, void *context)
diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c
index c94dd6802672..ef8c98e21098 100644
--- a/drivers/net/wireless/libertas/if_cs.c
+++ b/drivers/net/wireless/libertas/if_cs.c
@@ -754,14 +754,14 @@ static void if_cs_prog_firmware(struct lbs_private *priv, int ret,
754 if (ret == 0 && (card->model != MODEL_8305)) 754 if (ret == 0 && (card->model != MODEL_8305))
755 ret = if_cs_prog_real(card, mainfw); 755 ret = if_cs_prog_real(card, mainfw);
756 if (ret) 756 if (ret)
757 goto out; 757 return;
758 758
759 /* Now actually get the IRQ */ 759 /* Now actually get the IRQ */
760 ret = request_irq(card->p_dev->irq, if_cs_interrupt, 760 ret = request_irq(card->p_dev->irq, if_cs_interrupt,
761 IRQF_SHARED, DRV_NAME, card); 761 IRQF_SHARED, DRV_NAME, card);
762 if (ret) { 762 if (ret) {
763 pr_err("error in request_irq\n"); 763 pr_err("error in request_irq\n");
764 goto out; 764 return;
765 } 765 }
766 766
767 /* 767 /*
@@ -777,10 +777,6 @@ static void if_cs_prog_firmware(struct lbs_private *priv, int ret,
777 pr_err("could not activate card\n"); 777 pr_err("could not activate card\n");
778 free_irq(card->p_dev->irq, card); 778 free_irq(card->p_dev->irq, card);
779 } 779 }
780
781out:
782 release_firmware(helper);
783 release_firmware(mainfw);
784} 780}
785 781
786 782
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 45578335e420..991238afd1b6 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -708,20 +708,16 @@ static void if_sdio_do_prog_firmware(struct lbs_private *priv, int ret,
708 708
709 ret = if_sdio_prog_helper(card, helper); 709 ret = if_sdio_prog_helper(card, helper);
710 if (ret) 710 if (ret)
711 goto out; 711 return;
712 712
713 lbs_deb_sdio("Helper firmware loaded\n"); 713 lbs_deb_sdio("Helper firmware loaded\n");
714 714
715 ret = if_sdio_prog_real(card, mainfw); 715 ret = if_sdio_prog_real(card, mainfw);
716 if (ret) 716 if (ret)
717 goto out; 717 return;
718 718
719 lbs_deb_sdio("Firmware loaded\n"); 719 lbs_deb_sdio("Firmware loaded\n");
720 if_sdio_finish_power_on(card); 720 if_sdio_finish_power_on(card);
721
722out:
723 release_firmware(helper);
724 release_firmware(mainfw);
725} 721}
726 722
727static int if_sdio_prog_firmware(struct if_sdio_card *card) 723static int if_sdio_prog_firmware(struct if_sdio_card *card)
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index 5d39ec880d84..83669151bb82 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -1094,11 +1094,7 @@ static int if_spi_init_card(struct if_spi_card *card)
1094 goto out; 1094 goto out;
1095 1095
1096out: 1096out:
1097 release_firmware(helper);
1098 release_firmware(mainfw);
1099
1100 lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); 1097 lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
1101
1102 return err; 1098 return err;
1103} 1099}
1104 1100
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 27980778d992..dff08a2896a3 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -844,7 +844,7 @@ static void if_usb_prog_firmware(struct lbs_private *priv, int ret,
844 cardp->fw = fw; 844 cardp->fw = fw;
845 if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) { 845 if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) {
846 ret = -EINVAL; 846 ret = -EINVAL;
847 goto release_fw; 847 goto done;
848 } 848 }
849 849
850 /* Cancel any pending usb business */ 850 /* Cancel any pending usb business */
@@ -861,7 +861,7 @@ restart:
861 if (if_usb_submit_rx_urb_fwload(cardp) < 0) { 861 if (if_usb_submit_rx_urb_fwload(cardp) < 0) {
862 lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n"); 862 lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n");
863 ret = -EIO; 863 ret = -EIO;
864 goto release_fw; 864 goto done;
865 } 865 }
866 866
867 cardp->bootcmdresp = 0; 867 cardp->bootcmdresp = 0;
@@ -883,14 +883,14 @@ restart:
883 usb_kill_urb(cardp->tx_urb); 883 usb_kill_urb(cardp->tx_urb);
884 if (if_usb_submit_rx_urb(cardp) < 0) 884 if (if_usb_submit_rx_urb(cardp) < 0)
885 ret = -EIO; 885 ret = -EIO;
886 goto release_fw; 886 goto done;
887 } else if (cardp->bootcmdresp <= 0) { 887 } else if (cardp->bootcmdresp <= 0) {
888 if (--reset_count >= 0) { 888 if (--reset_count >= 0) {
889 if_usb_reset_device(cardp); 889 if_usb_reset_device(cardp);
890 goto restart; 890 goto restart;
891 } 891 }
892 ret = -EIO; 892 ret = -EIO;
893 goto release_fw; 893 goto done;
894 } 894 }
895 895
896 i = 0; 896 i = 0;
@@ -921,14 +921,14 @@ restart:
921 921
922 pr_info("FW download failure, time = %d ms\n", i * 100); 922 pr_info("FW download failure, time = %d ms\n", i * 100);
923 ret = -EIO; 923 ret = -EIO;
924 goto release_fw; 924 goto done;
925 } 925 }
926 926
927 cardp->priv->fw_ready = 1; 927 cardp->priv->fw_ready = 1;
928 if_usb_submit_rx_urb(cardp); 928 if_usb_submit_rx_urb(cardp);
929 929
930 if (lbs_start_card(priv)) 930 if (lbs_start_card(priv))
931 goto release_fw; 931 goto done;
932 932
933 if_usb_setup_firmware(priv); 933 if_usb_setup_firmware(priv);
934 934
@@ -939,11 +939,8 @@ restart:
939 if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL)) 939 if (lbs_host_sleep_cfg(priv, priv->wol_criteria, NULL))
940 priv->ehs_remove_supported = false; 940 priv->ehs_remove_supported = false;
941 941
942 release_fw:
943 release_firmware(cardp->fw);
944 cardp->fw = NULL;
945
946 done: 942 done:
943 cardp->fw = NULL;
947 lbs_deb_leave(LBS_DEB_USB); 944 lbs_deb_leave(LBS_DEB_USB);
948} 945}
949 946