Re: [PATCH v6] mmc: sdio: fix possible resource leaks in some error paths

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, 30 Jan 2023 at 13:58, Yang Yingliang <yangyingliang@xxxxxxxxxx> wrote:
>
> If sdio_add_func() or sdio_init_func() fails, sdio_remove_func() can
> not release the resources, because the sdio function is not presented
> in these two cases, it won't call of_node_put() or put_device().
>
> To fix these leaks, make sdio_func_present() only control whether
> device_del() needs to be called or not, then always call of_node_put()
> and put_device().
>
> In error case in sdio_init_func(), the reference of 'card->dev' is
> not get, to avoid redundant put in sdio_free_func_cis(), move the
> get_device() to sdio_alloc_func() and put_device() to sdio_release_func(),
> it can keep the get/put function be balanced.
>
> Without this patch, while doing fault inject test, it can get the
> following leak reports, after this fix, the leak is gone.
>
> unreferenced object 0xffff888112514000 (size 2048):
>   comm "kworker/3:2", pid 65, jiffies 4294741614 (age 124.774s)
>   hex dump (first 32 bytes):
>     00 e0 6f 12 81 88 ff ff 60 58 8d 06 81 88 ff ff  ..o.....`X......
>     10 40 51 12 81 88 ff ff 10 40 51 12 81 88 ff ff  .@Q......@Q.....
>   backtrace:
>     [<000000009e5931da>] kmalloc_trace+0x21/0x110
>     [<000000002f839ccb>] mmc_alloc_card+0x38/0xb0 [mmc_core]
>     [<0000000004adcbf6>] mmc_sdio_init_card+0xde/0x170 [mmc_core]
>     [<000000007538fea0>] mmc_attach_sdio+0xcb/0x1b0 [mmc_core]
>     [<00000000d4fdeba7>] mmc_rescan+0x54a/0x640 [mmc_core]
>
> unreferenced object 0xffff888112511000 (size 2048):
>   comm "kworker/3:2", pid 65, jiffies 4294741623 (age 124.766s)
>   hex dump (first 32 bytes):
>     00 40 51 12 81 88 ff ff e0 58 8d 06 81 88 ff ff  .@Q......X......
>     10 10 51 12 81 88 ff ff 10 10 51 12 81 88 ff ff  ..Q.......Q.....
>   backtrace:
>     [<000000009e5931da>] kmalloc_trace+0x21/0x110
>     [<00000000fcbe706c>] sdio_alloc_func+0x35/0x100 [mmc_core]
>     [<00000000c68f4b50>] mmc_attach_sdio.cold.18+0xb1/0x395 [mmc_core]
>     [<00000000d4fdeba7>] mmc_rescan+0x54a/0x640 [mmc_core]
>
> Fixes: 3d10a1ba0d37 ("sdio: fix reference counting in sdio_remove_func()")
> Signed-off-by: Yang Yingliang <yangyingliang@xxxxxxxxxx>

Applied for fixes and by adding a stable tag, thanks!

Kind regards
Uffe


> ---
> v5 -> v6:
>   Remove a fix tag.
>   Call get/put_device() without checking MMC_QUIRK_NONSTD_SDIO.
>
> v4 -> v5:
>   Merge to two pathes in one and add leak reports.
>   Fix wrong check in sdio_remove_func().
>   Move get/put_device() in sdio_alloc/release_func.
>
> v3 -> v4:
>   Drop patch1, keep calling put_device() to free memory,
>   set 'func->card' to NULL to avoid redundant put.
>
> v2 -> v3:
>   Change to call of_node_put() in remove() function to
>   fix node refcount leak.
>
> v1 -> v2:
>   Fix compile error in patch #2.
> ---
>  drivers/mmc/core/sdio_bus.c | 17 ++++++++++++++---
>  drivers/mmc/core/sdio_cis.c | 12 ------------
>  2 files changed, 14 insertions(+), 15 deletions(-)
>
> diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c
> index babf21a0adeb..f191a2a76f3b 100644
> --- a/drivers/mmc/core/sdio_bus.c
> +++ b/drivers/mmc/core/sdio_bus.c
> @@ -294,6 +294,12 @@ static void sdio_release_func(struct device *dev)
>         if (!(func->card->quirks & MMC_QUIRK_NONSTD_SDIO))
>                 sdio_free_func_cis(func);
>
> +       /*
> +        * We have now removed the link to the tuples in the
> +        * card structure, so remove the reference.
> +        */
> +       put_device(&func->card->dev);
> +
>         kfree(func->info);
>         kfree(func->tmpbuf);
>         kfree(func);
> @@ -324,6 +330,12 @@ struct sdio_func *sdio_alloc_func(struct mmc_card *card)
>
>         device_initialize(&func->dev);
>
> +       /*
> +        * We may link to tuples in the card structure,
> +        * we need make sure we have a reference to it.
> +        */
> +       get_device(&func->card->dev);
> +
>         func->dev.parent = &card->dev;
>         func->dev.bus = &sdio_bus_type;
>         func->dev.release = sdio_release_func;
> @@ -377,10 +389,9 @@ int sdio_add_func(struct sdio_func *func)
>   */
>  void sdio_remove_func(struct sdio_func *func)
>  {
> -       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..afaa6cab1adc 100644
> --- a/drivers/mmc/core/sdio_cis.c
> +++ b/drivers/mmc/core/sdio_cis.c
> @@ -403,12 +403,6 @@ int sdio_read_func_cis(struct sdio_func *func)
>         if (ret)
>                 return ret;
>
> -       /*
> -        * Since we've linked to tuples in the card structure,
> -        * we must make sure we have a reference to it.
> -        */
> -       get_device(&func->card->dev);
> -
>         /*
>          * Vendor/device id is optional for function CIS, so
>          * copy it from the card structure as needed.
> @@ -434,11 +428,5 @@ void sdio_free_func_cis(struct sdio_func *func)
>         }
>
>         func->tuples = NULL;
> -
> -       /*
> -        * We have now removed the link to the tuples in the
> -        * card structure, so remove the reference.
> -        */
> -       put_device(&func->card->dev);
>  }
>
> --
> 2.25.1
>



[Index of Archives]     [Linux Memonry Technology]     [Linux USB Devel]     [Linux Media]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux