From 6f1d3247662acef35ef6882528028b4b470baab4 Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Wed, 3 Mar 2021 13:20:49 +0100 Subject: [PATCH] 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: Ulf Hansson Link: https://lore.kernel.org/r/20210303122049.151986-4-ulf.hansson@linaro.org Signed-off-by: Ulf Hansson --- drivers/mmc/core/block.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 39308b3..02b6563 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) -- 2.7.4