diff mbox series

[3/3] mmc: block: Fix error path in mmc_blk_probe()

Message ID 20210303122049.151986-4-ulf.hansson@linaro.org
State New
Headers show
Series mmc: block: Cleanup mmc_blk_probe() path | expand

Commit Message

Ulf Hansson March 3, 2021, 12:20 p.m. UTC
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: Ulf Hansson <ulf.hansson@linaro.org>

---
 drivers/mmc/core/block.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

-- 
2.25.1
diff mbox series

Patch

diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c
index 39308b35a1fb..02b656305042 100644
--- a/drivers/mmc/core/block.c
+++ b/drivers/mmc/core/block.c
@@ -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;
 	}
 
@@ -2926,10 +2932,12 @@  static int mmc_blk_probe(struct mmc_card *card)
 
 	return 0;
 
- out:
+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)