Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9ec34f44 authored by Ulf Hansson's avatar Ulf Hansson Committed by Greg Kroah-Hartman
Browse files

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



commit a94a59f43749b4f8cd81b8be87c95f9ef898d19d upstream.

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


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 55d805ab
Loading
Loading
Loading
Loading
+27 −31
Original line number Original line Diff line number Diff line
@@ -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,
	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,


		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,
	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,
			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,
		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,
		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;
}
}