mmc: sdio: Fix several potential memory leaks in mmc_sdio_init_card()
authorUlf Hansson <ulf.hansson@linaro.org>
Thu, 30 Apr 2020 09:16:38 +0000 (11:16 +0200)
committerUlf Hansson <ulf.hansson@linaro.org>
Thu, 28 May 2020 09:21:03 +0000 (11:21 +0200)
Over the years, the code in mmc_sdio_init_card() has grown to become quite
messy. Unfortunate this has also lead to that several paths are leaking
memory in form of an allocated struct mmc_card, which includes additional
data, such as initialized struct device for example.

Unfortunate, it's a too complex task find each offending commit. Therefore,
this change fixes all memory leaks at once.

Cc: <stable@vger.kernel.org>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/r/20200430091640.455-3-ulf.hansson@linaro.org
drivers/mmc/core/sdio.c

index d35679e..20eed28 100644 (file)
@@ -584,7 +584,7 @@ try_again:
         */
        err = mmc_send_io_op_cond(host, ocr, &rocr);
        if (err)
-               goto err;
+               return err;
 
        /*
         * For SPI, enable CRC as appropriate.
@@ -592,17 +592,15 @@ try_again:
        if (mmc_host_is_spi(host)) {
                err = mmc_spi_set_crc(host, use_spi_crc);
                if (err)
-                       goto err;
+                       return err;
        }
 
        /*
         * Allocate card structure.
         */
        card = mmc_alloc_card(host, NULL);
-       if (IS_ERR(card)) {
-               err = PTR_ERR(card);
-               goto err;
-       }
+       if (IS_ERR(card))
+               return PTR_ERR(card);
 
        if ((rocr & R4_MEMORY_PRESENT) &&
            mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) {
@@ -610,19 +608,15 @@ try_again:
 
                if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO ||
                    memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) {
-                       mmc_remove_card(card);
-                       pr_debug("%s: Perhaps the card was replaced\n",
-                               mmc_hostname(host));
-                       return -ENOENT;
+                       err = -ENOENT;
+                       goto mismatch;
                }
        } else {
                card->type = MMC_TYPE_SDIO;
 
                if (oldcard && oldcard->type != MMC_TYPE_SDIO) {
-                       mmc_remove_card(card);
-                       pr_debug("%s: Perhaps the card was replaced\n",
-                               mmc_hostname(host));
-                       return -ENOENT;
+                       err = -ENOENT;
+                       goto mismatch;
                }
        }
 
@@ -677,7 +671,7 @@ try_again:
        if (!oldcard && card->type == MMC_TYPE_SD_COMBO) {
                err = mmc_sd_get_csd(host, card);
                if (err)
-                       return err;
+                       goto remove;
 
                mmc_decode_cid(card);
        }
@@ -704,7 +698,12 @@ try_again:
                        mmc_set_timing(card->host, MMC_TIMING_SD_HS);
                }
 
-               goto finish;
+               if (oldcard)
+                       mmc_remove_card(card);
+               else
+                       host->card = card;
+
+               return 0;
        }
 
        /*
@@ -730,16 +729,14 @@ try_again:
                goto remove;
 
        if (oldcard) {
-               int same = (card->cis.vendor == oldcard->cis.vendor &&
-                           card->cis.device == oldcard->cis.device);
-               mmc_remove_card(card);
-               if (!same) {
-                       pr_debug("%s: Perhaps the card was replaced\n",
-                               mmc_hostname(host));
-                       return -ENOENT;
+               if (card->cis.vendor == oldcard->cis.vendor &&
+                   card->cis.device == oldcard->cis.device) {
+                       mmc_remove_card(card);
+                       card = oldcard;
+               } else {
+                       err = -ENOENT;
+                       goto mismatch;
                }
-
-               card = oldcard;
        }
        card->ocr = ocr_card;
        mmc_fixup_device(card, sdio_fixup_methods);
@@ -800,16 +797,15 @@ try_again:
                err = -EINVAL;
                goto remove;
        }
-finish:
-       if (!oldcard)
-               host->card = card;
+
+       host->card = card;
        return 0;
 
+mismatch:
+       pr_debug("%s: Perhaps the card was replaced\n", mmc_hostname(host));
 remove:
-       if (!oldcard)
+       if (oldcard != card)
                mmc_remove_card(card);
-
-err:
        return err;
 }