Commit a94a59f4 authored by Ulf Hansson's avatar Ulf Hansson

mmc: sdio: Fix several potential memory leaks in mmc_sdio_init_card()

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: default avatarUlf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/r/20200430091640.455-3-ulf.hansson@linaro.org
parent f04086c2
...@@ -584,7 +584,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, ...@@ -584,7 +584,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
*/ */
err = mmc_send_io_op_cond(host, ocr, &rocr); err = mmc_send_io_op_cond(host, ocr, &rocr);
if (err) if (err)
goto err; return err;
/* /*
* For SPI, enable CRC as appropriate. * For SPI, enable CRC as appropriate.
...@@ -592,17 +592,15 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, ...@@ -592,17 +592,15 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
if (mmc_host_is_spi(host)) { if (mmc_host_is_spi(host)) {
err = mmc_spi_set_crc(host, use_spi_crc); err = mmc_spi_set_crc(host, use_spi_crc);
if (err) if (err)
goto err; return err;
} }
/* /*
* Allocate card structure. * Allocate card structure.
*/ */
card = mmc_alloc_card(host, NULL); card = mmc_alloc_card(host, NULL);
if (IS_ERR(card)) { if (IS_ERR(card))
err = PTR_ERR(card); return PTR_ERR(card);
goto err;
}
if ((rocr & R4_MEMORY_PRESENT) && if ((rocr & R4_MEMORY_PRESENT) &&
mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) { mmc_sd_get_cid(host, ocr & rocr, card->raw_cid, NULL) == 0) {
...@@ -610,19 +608,15 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, ...@@ -610,19 +608,15 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO || if (oldcard && (oldcard->type != MMC_TYPE_SD_COMBO ||
memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) { memcmp(card->raw_cid, oldcard->raw_cid, sizeof(card->raw_cid)) != 0)) {
mmc_remove_card(card); err = -ENOENT;
pr_debug("%s: Perhaps the card was replaced\n", goto mismatch;
mmc_hostname(host));
return -ENOENT;
} }
} else { } else {
card->type = MMC_TYPE_SDIO; card->type = MMC_TYPE_SDIO;
if (oldcard && oldcard->type != MMC_TYPE_SDIO) { if (oldcard && oldcard->type != MMC_TYPE_SDIO) {
mmc_remove_card(card); err = -ENOENT;
pr_debug("%s: Perhaps the card was replaced\n", goto mismatch;
mmc_hostname(host));
return -ENOENT;
} }
} }
...@@ -677,7 +671,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, ...@@ -677,7 +671,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
if (!oldcard && card->type == MMC_TYPE_SD_COMBO) { if (!oldcard && card->type == MMC_TYPE_SD_COMBO) {
err = mmc_sd_get_csd(host, card); err = mmc_sd_get_csd(host, card);
if (err) if (err)
return err; goto remove;
mmc_decode_cid(card); mmc_decode_cid(card);
} }
...@@ -704,7 +698,12 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, ...@@ -704,7 +698,12 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
mmc_set_timing(card->host, MMC_TIMING_SD_HS); 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 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, ...@@ -730,16 +729,14 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
goto remove; goto remove;
if (oldcard) { if (oldcard) {
int same = (card->cis.vendor == oldcard->cis.vendor && if (card->cis.vendor == oldcard->cis.vendor &&
card->cis.device == oldcard->cis.device); card->cis.device == oldcard->cis.device) {
mmc_remove_card(card); mmc_remove_card(card);
if (!same) {
pr_debug("%s: Perhaps the card was replaced\n",
mmc_hostname(host));
return -ENOENT;
}
card = oldcard; card = oldcard;
} else {
err = -ENOENT;
goto mismatch;
}
} }
card->ocr = ocr_card; card->ocr = ocr_card;
mmc_fixup_device(card, sdio_fixup_methods); mmc_fixup_device(card, sdio_fixup_methods);
...@@ -800,16 +797,15 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, ...@@ -800,16 +797,15 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr,
err = -EINVAL; err = -EINVAL;
goto remove; goto remove;
} }
finish:
if (!oldcard)
host->card = card; host->card = card;
return 0; return 0;
mismatch:
pr_debug("%s: Perhaps the card was replaced\n", mmc_hostname(host));
remove: remove:
if (!oldcard) if (oldcard != card)
mmc_remove_card(card); mmc_remove_card(card);
err:
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment