diff mbox series

[v4,2/2] mmc: sdio: fix possible memory leak in some error path

Message ID 20221110025530.4106568-3-yangyingliang@huawei.com (mailing list archive)
State New, archived
Headers show
Series mmc: sdio: fixes some leaks | expand

Commit Message

Yang Yingliang Nov. 10, 2022, 2:55 a.m. UTC
If sdio_add_func() or sdio_init_func() fails, sdio_remove_func() can
not free the memory, because the sdio function is not presented in
these two cases, it won't call put_device().

To fix these leaks, make sdio_func_present() only control whether
device_del() needs to be called or not. Then, put_device() is called
to give up the reference which was set in device_initialize(), the
memory can be freed in sdio_release_func().

In error case in sdio_init_func(), the reference of 'card->dev' is
not get, so set 'func->card' to NULL to avoid redundant put in
sdio_free_func_cis().

Fixes: 3d10a1ba0d37 ("sdio: fix reference counting in sdio_remove_func()")
Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
---
 drivers/mmc/core/sdio.c     | 1 +
 drivers/mmc/core/sdio_bus.c | 8 ++++----
 drivers/mmc/core/sdio_cis.c | 3 ++-
 3 files changed, 7 insertions(+), 5 deletions(-)

Comments

Yang Yingliang Dec. 13, 2022, 8:48 a.m. UTC | #1
Sorry, this patch is wrong, please ignore this patchset.

On 2022/11/10 10:55, Yang Yingliang wrote:
> If sdio_add_func() or sdio_init_func() fails, sdio_remove_func() can
> not free the memory, because the sdio function is not presented in
> these two cases, it won't call put_device().
>
> To fix these leaks, make sdio_func_present() only control whether
> device_del() needs to be called or not. Then, put_device() is called
> to give up the reference which was set in device_initialize(), the
> memory can be freed in sdio_release_func().
>
> In error case in sdio_init_func(), the reference of 'card->dev' is
> not get, so set 'func->card' to NULL to avoid redundant put in
> sdio_free_func_cis().
>
> Fixes: 3d10a1ba0d37 ("sdio: fix reference counting in sdio_remove_func()")
> Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
> ---
>   drivers/mmc/core/sdio.c     | 1 +
>   drivers/mmc/core/sdio_bus.c | 8 ++++----
>   drivers/mmc/core/sdio_cis.c | 3 ++-
>   3 files changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
> index f64b9ac76a5c..ff95fb6aa741 100644
> --- a/drivers/mmc/core/sdio.c
> +++ b/drivers/mmc/core/sdio.c
> @@ -137,6 +137,7 @@ static int sdio_init_func(struct mmc_card *card, unsigned int fn)
>   	 * It is okay to remove the function here even though we hold
>   	 * the host lock as we haven't registered the device yet.
>   	 */
> +	func->card = NULL;
>   	sdio_remove_func(func);
>   	return ret;
>   }
> diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
> index 266639504a94..da561658bdae 100644
> --- a/drivers/mmc/core/sdio_bus.c
> +++ b/drivers/mmc/core/sdio_bus.c
> @@ -377,11 +377,11 @@ int sdio_add_func(struct sdio_func *func)
>    */
>   void sdio_remove_func(struct sdio_func *func)
>   {
> -	of_node_put(func->dev.of_node);
> -	if (!sdio_func_present(func))
> -		return;
> +	if (!sdio_func_present(func)) {
> +		device_del(&func->dev);
> +	}
>   
> -	device_del(&func->dev);
> +	of_node_put(func->dev.of_node);
>   	put_device(&func->dev);
>   }
>   
> diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
> index a705ba6eff5b..d374460fba9b 100644
> --- a/drivers/mmc/core/sdio_cis.c
> +++ b/drivers/mmc/core/sdio_cis.c
> @@ -439,6 +439,7 @@ void sdio_free_func_cis(struct sdio_func *func)
>   	 * We have now removed the link to the tuples in the
>   	 * card structure, so remove the reference.
>   	 */
> -	put_device(&func->card->dev);
> +	if (func->card)
> +		put_device(&func->card->dev);
>   }
>
diff mbox series

Patch

diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c
index f64b9ac76a5c..ff95fb6aa741 100644
--- a/drivers/mmc/core/sdio.c
+++ b/drivers/mmc/core/sdio.c
@@ -137,6 +137,7 @@  static int sdio_init_func(struct mmc_card *card, unsigned int fn)
 	 * It is okay to remove the function here even though we hold
 	 * the host lock as we haven't registered the device yet.
 	 */
+	func->card = NULL;
 	sdio_remove_func(func);
 	return ret;
 }
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
index 266639504a94..da561658bdae 100644
--- a/drivers/mmc/core/sdio_bus.c
+++ b/drivers/mmc/core/sdio_bus.c
@@ -377,11 +377,11 @@  int sdio_add_func(struct sdio_func *func)
  */
 void sdio_remove_func(struct sdio_func *func)
 {
-	of_node_put(func->dev.of_node);
-	if (!sdio_func_present(func))
-		return;
+	if (!sdio_func_present(func)) {
+		device_del(&func->dev);
+	}
 
-	device_del(&func->dev);
+	of_node_put(func->dev.of_node);
 	put_device(&func->dev);
 }
 
diff --git a/drivers/mmc/core/sdio_cis.c b/drivers/mmc/core/sdio_cis.c
index a705ba6eff5b..d374460fba9b 100644
--- a/drivers/mmc/core/sdio_cis.c
+++ b/drivers/mmc/core/sdio_cis.c
@@ -439,6 +439,7 @@  void sdio_free_func_cis(struct sdio_func *func)
 	 * We have now removed the link to the tuples in the
 	 * card structure, so remove the reference.
 	 */
-	put_device(&func->card->dev);
+	if (func->card)
+		put_device(&func->card->dev);
 }