From: s.nawrocki@samsung.com (Sylwester Nawrocki)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 1/2] clk: Fix double free due to devm_clk_register()
Date: Wed, 14 May 2014 13:26:29 +0200 [thread overview]
Message-ID: <537352E5.20901@samsung.com> (raw)
In-Reply-To: <1397863783-10728-2-git-send-email-sboyd@codeaurora.org>
On 19/04/14 01:29, Stephen Boyd wrote:
> Now that clk_unregister() frees the struct clk we're
> unregistering we'll free memory twice: first we'll call kfree()
> in __clk_release() with an address kmalloc doesn't know about and
> second we'll call kfree() in the devres layer. Remove the
> allocation of struct clk in devm_clk_register() and let
> clk_release() handle it. This fixes slab errors like:
>
> =============================================================================
> BUG kmalloc-128 (Not tainted): Invalid object pointer 0xed08e8d0
> -----------------------------------------------------------------------------
>
> Disabling lock debugging due to kernel taint
> INFO: Slab 0xeec503f8 objects=25 used=15 fp=0xed08ea00 flags=0x4081
> CPU: 2 PID: 73 Comm: rmmod Tainted: G B 3.14.0-11032-g526e9c764381 #34
> [<c0014be0>] (unwind_backtrace) from [<c0012240>] (show_stack+0x10/0x14)
> [<c0012240>] (show_stack) from [<c04b74dc>] (dump_stack+0x70/0xbc)
> [<c04b74dc>] (dump_stack) from [<c00f6778>] (slab_err+0x74/0x84)
> [<c00f6778>] (slab_err) from [<c04b6278>] (free_debug_processing+0x2cc/0x31c)
> [<c04b6278>] (free_debug_processing) from [<c04b6300>] (__slab_free+0x38/0x41c)
> [<c04b6300>] (__slab_free) from [<c03931bc>] (clk_unregister+0xd4/0x140)
> [<c03931bc>] (clk_unregister) from [<c02fb774>] (release_nodes+0x164/0x1d8)
> [<c02fb774>] (release_nodes) from [<c02f8698>] (__device_release_driver+0x60/0xb0)
> [<c02f8698>] (__device_release_driver) from [<c02f9080>] (driver_detach+0xb4/0xb8)
> [<c02f9080>] (driver_detach) from [<c02f8480>] (bus_remove_driver+0x5c/0xc4)
> [<c02f8480>] (bus_remove_driver) from [<c008c9b8>] (SyS_delete_module+0x148/0x1d8)
> [<c008c9b8>] (SyS_delete_module) from [<c000ef80>] (ret_fast_syscall+0x0/0x48)
> FIX kmalloc-128: Object at 0xed08e8d0 not freed
>
> Fixes: fcb0ee6a3d33 (clk: Implement clk_unregister)
> Cc: Jiada Wang <jiada_wang@mentor.com>
> Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Cc: Kyungmin Park <kyungmin.park@samsung.com>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Thank you for correcting this, and my apologies for introducing this bug.
Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
> drivers/clk/clk.c | 71 +++++++++++++++++++++++--------------------------------
> 1 file changed, 30 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index dff0373f53c1..f71093bf83ab 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1984,9 +1984,28 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
> }
> EXPORT_SYMBOL_GPL(__clk_register);
>
> -static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
> +/**
> + * clk_register - allocate a new clock, register it and return an opaque cookie
> + * @dev: device that is registering this clock
> + * @hw: link to hardware-specific clock data
> + *
> + * clk_register is the primary interface for populating the clock tree with new
> + * clock nodes. It returns a pointer to the newly allocated struct clk which
> + * cannot be dereferenced by driver code but may be used in conjuction with the
> + * rest of the clock API. In the event of an error clk_register will return an
> + * error code; drivers must test for an error code after calling clk_register.
> + */
> +struct clk *clk_register(struct device *dev, struct clk_hw *hw)
> {
> int i, ret;
> + struct clk *clk;
> +
> + clk = kzalloc(sizeof(*clk), GFP_KERNEL);
> + if (!clk) {
> + pr_err("%s: could not allocate clk\n", __func__);
> + ret = -ENOMEM;
> + goto fail_out;
> + }
>
> clk->name = kstrdup(hw->init->name, GFP_KERNEL);
> if (!clk->name) {
> @@ -2026,7 +2045,7 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
>
> ret = __clk_init(dev, clk);
> if (!ret)
> - return 0;
> + return clk;
>
> fail_parent_names_copy:
> while (--i >= 0)
> @@ -2035,36 +2054,6 @@ fail_parent_names_copy:
> fail_parent_names:
> kfree(clk->name);
> fail_name:
> - return ret;
> -}
> -
> -/**
> - * clk_register - allocate a new clock, register it and return an opaque cookie
> - * @dev: device that is registering this clock
> - * @hw: link to hardware-specific clock data
> - *
> - * clk_register is the primary interface for populating the clock tree with new
> - * clock nodes. It returns a pointer to the newly allocated struct clk which
> - * cannot be dereferenced by driver code but may be used in conjuction with the
> - * rest of the clock API. In the event of an error clk_register will return an
> - * error code; drivers must test for an error code after calling clk_register.
> - */
> -struct clk *clk_register(struct device *dev, struct clk_hw *hw)
> -{
> - int ret;
> - struct clk *clk;
> -
> - clk = kzalloc(sizeof(*clk), GFP_KERNEL);
> - if (!clk) {
> - pr_err("%s: could not allocate clk\n", __func__);
> - ret = -ENOMEM;
> - goto fail_out;
> - }
> -
> - ret = _clk_register(dev, hw, clk);
> - if (!ret)
> - return clk;
> -
> kfree(clk);
> fail_out:
> return ERR_PTR(ret);
> @@ -2173,7 +2162,7 @@ EXPORT_SYMBOL_GPL(clk_unregister);
>
> static void devm_clk_release(struct device *dev, void *res)
> {
> - clk_unregister(res);
> + clk_unregister(*(struct clk **)res);
> }
>
> /**
> @@ -2188,18 +2177,18 @@ static void devm_clk_release(struct device *dev, void *res)
> struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
> {
> struct clk *clk;
> - int ret;
> + struct clk **clkp;
>
> - clk = devres_alloc(devm_clk_release, sizeof(*clk), GFP_KERNEL);
> - if (!clk)
> + clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL);
> + if (!clkp)
> return ERR_PTR(-ENOMEM);
>
> - ret = _clk_register(dev, hw, clk);
> - if (!ret) {
> - devres_add(dev, clk);
> + clk = clk_register(dev, hw);
> + if (!IS_ERR(clk)) {
> + *clkp = clk;
> + devres_add(dev, clkp);
> } else {
> - devres_free(clk);
> - clk = ERR_PTR(ret);
> + devres_free(clkp);
> }
>
> return clk;
>
--
Sylwester Nawrocki
Samsung R&D Institute Poland
WARNING: multiple messages have this Message-ID (diff)
From: Sylwester Nawrocki <s.nawrocki@samsung.com>
To: Stephen Boyd <sboyd@codeaurora.org>
Cc: Mike Turquette <mturquette@linaro.org>,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org,
Jiada Wang <jiada_wang@mentor.com>,
Kyungmin Park <kyungmin.park@samsung.com>
Subject: Re: [PATCH 1/2] clk: Fix double free due to devm_clk_register()
Date: Wed, 14 May 2014 13:26:29 +0200 [thread overview]
Message-ID: <537352E5.20901@samsung.com> (raw)
In-Reply-To: <1397863783-10728-2-git-send-email-sboyd@codeaurora.org>
On 19/04/14 01:29, Stephen Boyd wrote:
> Now that clk_unregister() frees the struct clk we're
> unregistering we'll free memory twice: first we'll call kfree()
> in __clk_release() with an address kmalloc doesn't know about and
> second we'll call kfree() in the devres layer. Remove the
> allocation of struct clk in devm_clk_register() and let
> clk_release() handle it. This fixes slab errors like:
>
> =============================================================================
> BUG kmalloc-128 (Not tainted): Invalid object pointer 0xed08e8d0
> -----------------------------------------------------------------------------
>
> Disabling lock debugging due to kernel taint
> INFO: Slab 0xeec503f8 objects=25 used=15 fp=0xed08ea00 flags=0x4081
> CPU: 2 PID: 73 Comm: rmmod Tainted: G B 3.14.0-11032-g526e9c764381 #34
> [<c0014be0>] (unwind_backtrace) from [<c0012240>] (show_stack+0x10/0x14)
> [<c0012240>] (show_stack) from [<c04b74dc>] (dump_stack+0x70/0xbc)
> [<c04b74dc>] (dump_stack) from [<c00f6778>] (slab_err+0x74/0x84)
> [<c00f6778>] (slab_err) from [<c04b6278>] (free_debug_processing+0x2cc/0x31c)
> [<c04b6278>] (free_debug_processing) from [<c04b6300>] (__slab_free+0x38/0x41c)
> [<c04b6300>] (__slab_free) from [<c03931bc>] (clk_unregister+0xd4/0x140)
> [<c03931bc>] (clk_unregister) from [<c02fb774>] (release_nodes+0x164/0x1d8)
> [<c02fb774>] (release_nodes) from [<c02f8698>] (__device_release_driver+0x60/0xb0)
> [<c02f8698>] (__device_release_driver) from [<c02f9080>] (driver_detach+0xb4/0xb8)
> [<c02f9080>] (driver_detach) from [<c02f8480>] (bus_remove_driver+0x5c/0xc4)
> [<c02f8480>] (bus_remove_driver) from [<c008c9b8>] (SyS_delete_module+0x148/0x1d8)
> [<c008c9b8>] (SyS_delete_module) from [<c000ef80>] (ret_fast_syscall+0x0/0x48)
> FIX kmalloc-128: Object at 0xed08e8d0 not freed
>
> Fixes: fcb0ee6a3d33 (clk: Implement clk_unregister)
> Cc: Jiada Wang <jiada_wang@mentor.com>
> Cc: Sylwester Nawrocki <s.nawrocki@samsung.com>
> Cc: Kyungmin Park <kyungmin.park@samsung.com>
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
Thank you for correcting this, and my apologies for introducing this bug.
Acked-by: Sylwester Nawrocki <s.nawrocki@samsung.com>
> ---
> drivers/clk/clk.c | 71 +++++++++++++++++++++++--------------------------------
> 1 file changed, 30 insertions(+), 41 deletions(-)
>
> diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
> index dff0373f53c1..f71093bf83ab 100644
> --- a/drivers/clk/clk.c
> +++ b/drivers/clk/clk.c
> @@ -1984,9 +1984,28 @@ struct clk *__clk_register(struct device *dev, struct clk_hw *hw)
> }
> EXPORT_SYMBOL_GPL(__clk_register);
>
> -static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
> +/**
> + * clk_register - allocate a new clock, register it and return an opaque cookie
> + * @dev: device that is registering this clock
> + * @hw: link to hardware-specific clock data
> + *
> + * clk_register is the primary interface for populating the clock tree with new
> + * clock nodes. It returns a pointer to the newly allocated struct clk which
> + * cannot be dereferenced by driver code but may be used in conjuction with the
> + * rest of the clock API. In the event of an error clk_register will return an
> + * error code; drivers must test for an error code after calling clk_register.
> + */
> +struct clk *clk_register(struct device *dev, struct clk_hw *hw)
> {
> int i, ret;
> + struct clk *clk;
> +
> + clk = kzalloc(sizeof(*clk), GFP_KERNEL);
> + if (!clk) {
> + pr_err("%s: could not allocate clk\n", __func__);
> + ret = -ENOMEM;
> + goto fail_out;
> + }
>
> clk->name = kstrdup(hw->init->name, GFP_KERNEL);
> if (!clk->name) {
> @@ -2026,7 +2045,7 @@ static int _clk_register(struct device *dev, struct clk_hw *hw, struct clk *clk)
>
> ret = __clk_init(dev, clk);
> if (!ret)
> - return 0;
> + return clk;
>
> fail_parent_names_copy:
> while (--i >= 0)
> @@ -2035,36 +2054,6 @@ fail_parent_names_copy:
> fail_parent_names:
> kfree(clk->name);
> fail_name:
> - return ret;
> -}
> -
> -/**
> - * clk_register - allocate a new clock, register it and return an opaque cookie
> - * @dev: device that is registering this clock
> - * @hw: link to hardware-specific clock data
> - *
> - * clk_register is the primary interface for populating the clock tree with new
> - * clock nodes. It returns a pointer to the newly allocated struct clk which
> - * cannot be dereferenced by driver code but may be used in conjuction with the
> - * rest of the clock API. In the event of an error clk_register will return an
> - * error code; drivers must test for an error code after calling clk_register.
> - */
> -struct clk *clk_register(struct device *dev, struct clk_hw *hw)
> -{
> - int ret;
> - struct clk *clk;
> -
> - clk = kzalloc(sizeof(*clk), GFP_KERNEL);
> - if (!clk) {
> - pr_err("%s: could not allocate clk\n", __func__);
> - ret = -ENOMEM;
> - goto fail_out;
> - }
> -
> - ret = _clk_register(dev, hw, clk);
> - if (!ret)
> - return clk;
> -
> kfree(clk);
> fail_out:
> return ERR_PTR(ret);
> @@ -2173,7 +2162,7 @@ EXPORT_SYMBOL_GPL(clk_unregister);
>
> static void devm_clk_release(struct device *dev, void *res)
> {
> - clk_unregister(res);
> + clk_unregister(*(struct clk **)res);
> }
>
> /**
> @@ -2188,18 +2177,18 @@ static void devm_clk_release(struct device *dev, void *res)
> struct clk *devm_clk_register(struct device *dev, struct clk_hw *hw)
> {
> struct clk *clk;
> - int ret;
> + struct clk **clkp;
>
> - clk = devres_alloc(devm_clk_release, sizeof(*clk), GFP_KERNEL);
> - if (!clk)
> + clkp = devres_alloc(devm_clk_release, sizeof(*clkp), GFP_KERNEL);
> + if (!clkp)
> return ERR_PTR(-ENOMEM);
>
> - ret = _clk_register(dev, hw, clk);
> - if (!ret) {
> - devres_add(dev, clk);
> + clk = clk_register(dev, hw);
> + if (!IS_ERR(clk)) {
> + *clkp = clk;
> + devres_add(dev, clkp);
> } else {
> - devres_free(clk);
> - clk = ERR_PTR(ret);
> + devres_free(clkp);
> }
>
> return clk;
>
--
Sylwester Nawrocki
Samsung R&D Institute Poland
next prev parent reply other threads:[~2014-05-14 11:26 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-18 23:29 [PATCH 0/2] Clock unregistration fixes Stephen Boyd
2014-04-18 23:29 ` Stephen Boyd
2014-04-18 23:29 ` [PATCH 1/2] clk: Fix double free due to devm_clk_register() Stephen Boyd
2014-04-18 23:29 ` Stephen Boyd
2014-05-14 11:26 ` Sylwester Nawrocki [this message]
2014-05-14 11:26 ` Sylwester Nawrocki
2014-04-18 23:29 ` [PATCH 2/2] clk: Fix slab corruption in clk_unregister() Stephen Boyd
2014-04-18 23:29 ` Stephen Boyd
2014-05-14 11:27 ` Sylwester Nawrocki
2014-05-14 11:27 ` Sylwester Nawrocki
2014-04-29 7:24 ` [PATCH 0/2] Clock unregistration fixes Mike Turquette
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=537352E5.20901@samsung.com \
--to=s.nawrocki@samsung.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.