Commit 6f1d3247 authored by Ulf Hansson's avatar Ulf Hansson
Browse files

mmc: block: Fix error path in mmc_blk_probe()



Returning zero to indicate success, when we actually have failed to probe
is wrong. As a matter of fact, it leads to that mmc_blk_remove() gets
called at a card removal and then triggers "NULL pointer dereference"
splats. This is because mmc_blk_remove() relies on data structures and
pointers to be setup from mmc_blk_probe(), of course.

There have been no errors reported about this, which is most likely because
mmc_blk_probe() never fails like this. Nevertheless, let's fix the code by
propagating the error codes correctly and prevent us from leaking memory by
calling also destroy_workqueue() in the error path.

Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Link: https://lore.kernel.org/r/20210303122049.151986-4-ulf.hansson@linaro.org


Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
parent ce999ed1
Loading
Loading
Loading
Loading
+15 −7
Original line number Diff line number Diff line
@@ -2876,6 +2876,7 @@ static void mmc_blk_remove_debugfs(struct mmc_card *card,
static int mmc_blk_probe(struct mmc_card *card)
{
	struct mmc_blk_data *md, *part_md;
	int ret = 0;

	/*
	 * Check that the card supports the command class(es) we need.
@@ -2893,19 +2894,24 @@ static int mmc_blk_probe(struct mmc_card *card)
	}

	md = mmc_blk_alloc(card);
	if (IS_ERR(md))
		return PTR_ERR(md);
	if (IS_ERR(md)) {
		ret = PTR_ERR(md);
		goto out_free;
	}

	if (mmc_blk_alloc_parts(card, md))
	ret = mmc_blk_alloc_parts(card, md);
	if (ret)
		goto out;

	dev_set_drvdata(&card->dev, md);

	if (mmc_add_disk(md))
	ret = mmc_add_disk(md);
	if (ret)
		goto out;

	list_for_each_entry(part_md, &md->part, part) {
		if (mmc_add_disk(part_md))
		ret = mmc_add_disk(part_md);
		if (ret)
			goto out;
	}

@@ -2929,7 +2935,9 @@ static int mmc_blk_probe(struct mmc_card *card)
out:
	mmc_blk_remove_parts(card, md);
	mmc_blk_remove_req(md);
	return 0;
out_free:
	destroy_workqueue(card->complete_wq);
	return ret;
}

static void mmc_blk_remove(struct mmc_card *card)