diff mbox series

clk: Fix memory leak in clk_unregister()

Message ID 20191022071153.21118-1-kishon@ti.com
State Accepted
Commit 8247470772beb38822f226c99a2ed8c195f6b438
Headers show
Series clk: Fix memory leak in clk_unregister() | expand

Commit Message

Kishon Vijay Abraham I Oct. 22, 2019, 7:11 a.m. UTC
Memory allocated in alloc_clk() for 'struct clk' and
'const char *con_id' while invoking clk_register() is never freed
in clk_unregister(), resulting in kmemleak showing the following
backtrace.

  backtrace:
    [<00000000546f5dd0>] kmem_cache_alloc+0x18c/0x270
    [<0000000073a32862>] alloc_clk+0x30/0x70
    [<0000000082942480>] __clk_register+0xc8/0x760
    [<000000005c859fca>] devm_clk_register+0x54/0xb0
    [<00000000868834a8>] 0xffff800008c60950
    [<00000000d5a80534>] platform_drv_probe+0x50/0xa0
    [<000000001b3889fc>] really_probe+0x108/0x348
    [<00000000953fa60a>] driver_probe_device+0x58/0x100
    [<0000000008acc17c>] device_driver_attach+0x6c/0x90
    [<0000000022813df3>] __driver_attach+0x84/0xc8
    [<00000000448d5443>] bus_for_each_dev+0x74/0xc8
    [<00000000294aa93f>] driver_attach+0x20/0x28
    [<00000000e5e52626>] bus_add_driver+0x148/0x1f0
    [<000000001de21efc>] driver_register+0x60/0x110
    [<00000000af07c068>] __platform_driver_register+0x40/0x48
    [<0000000060fa80ee>] 0xffff800008c66020

Fix it here.

Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>
Cc: Tero Kristo <t-kristo@ti.com>
Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

---
 drivers/clk/clk.c | 1 +
 1 file changed, 1 insertion(+)

-- 
2.17.1

Comments

Stephen Boyd Oct. 22, 2019, 6:51 p.m. UTC | #1
Quoting Kishon Vijay Abraham I (2019-10-22 00:11:53)
> Memory allocated in alloc_clk() for 'struct clk' and

> 'const char *con_id' while invoking clk_register() is never freed

> in clk_unregister(), resulting in kmemleak showing the following

> backtrace.

> 

>   backtrace:

>     [<00000000546f5dd0>] kmem_cache_alloc+0x18c/0x270

>     [<0000000073a32862>] alloc_clk+0x30/0x70

>     [<0000000082942480>] __clk_register+0xc8/0x760

>     [<000000005c859fca>] devm_clk_register+0x54/0xb0

>     [<00000000868834a8>] 0xffff800008c60950

>     [<00000000d5a80534>] platform_drv_probe+0x50/0xa0

>     [<000000001b3889fc>] really_probe+0x108/0x348

>     [<00000000953fa60a>] driver_probe_device+0x58/0x100

>     [<0000000008acc17c>] device_driver_attach+0x6c/0x90

>     [<0000000022813df3>] __driver_attach+0x84/0xc8

>     [<00000000448d5443>] bus_for_each_dev+0x74/0xc8

>     [<00000000294aa93f>] driver_attach+0x20/0x28

>     [<00000000e5e52626>] bus_add_driver+0x148/0x1f0

>     [<000000001de21efc>] driver_register+0x60/0x110

>     [<00000000af07c068>] __platform_driver_register+0x40/0x48

>     [<0000000060fa80ee>] 0xffff800008c66020

> 

> Fix it here.


Do you have some Fixes tag for this? Looks OK to me, but I wonder if we
should also assign hw->clk to NULL after unregister frees it. There are
probably other problems around unregistration and reference counting
that we haven't found so far so I'm worried this doesn't solve all the
problems by just freeing the clk pointer.

For example, anything referencing the clk pointer freed here will now
start trying to dereference freed memory. For most cases we've replaced
struct clk with struct clk_core in the clk framework so I hope this
pointer isn't used very much at all. A quick grep shows that it is
returned from clk_get_parent() and __clk_lookup(). We really need to
kill off __clk_lookup() and replace it with something else, and
clk_get_parent() needs to generate a different clk and have callers call
clk_put() on the returned pointer. Long story short I think this is OK!
Stephen Boyd Nov. 19, 2019, 10:19 p.m. UTC | #2
Quoting Kishon Vijay Abraham I (2019-10-22 00:11:53)
> Memory allocated in alloc_clk() for 'struct clk' and

> 'const char *con_id' while invoking clk_register() is never freed

> in clk_unregister(), resulting in kmemleak showing the following

> backtrace.

> 

>   backtrace:

>     [<00000000546f5dd0>] kmem_cache_alloc+0x18c/0x270

>     [<0000000073a32862>] alloc_clk+0x30/0x70

>     [<0000000082942480>] __clk_register+0xc8/0x760

>     [<000000005c859fca>] devm_clk_register+0x54/0xb0

>     [<00000000868834a8>] 0xffff800008c60950

>     [<00000000d5a80534>] platform_drv_probe+0x50/0xa0

>     [<000000001b3889fc>] really_probe+0x108/0x348

>     [<00000000953fa60a>] driver_probe_device+0x58/0x100

>     [<0000000008acc17c>] device_driver_attach+0x6c/0x90

>     [<0000000022813df3>] __driver_attach+0x84/0xc8

>     [<00000000448d5443>] bus_for_each_dev+0x74/0xc8

>     [<00000000294aa93f>] driver_attach+0x20/0x28

>     [<00000000e5e52626>] bus_add_driver+0x148/0x1f0

>     [<000000001de21efc>] driver_register+0x60/0x110

>     [<00000000af07c068>] __platform_driver_register+0x40/0x48

>     [<0000000060fa80ee>] 0xffff800008c66020

> 

> Fix it here.

> 

> Cc: Tomi Valkeinen <tomi.valkeinen@ti.com>

> Cc: Tero Kristo <t-kristo@ti.com>

> Signed-off-by: Kishon Vijay Abraham I <kishon@ti.com>

> ---


Applied to clk-next

I also added a fixes tag for the best I could guess.
diff mbox series

Patch

diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 1c677d7f7f53..2f2eea26c375 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -3879,6 +3879,7 @@  void clk_unregister(struct clk *clk)
 					__func__, clk->core->name);
 
 	kref_put(&clk->core->ref, __clk_release);
+	free_clk(clk);
 unlock:
 	clk_prepare_unlock();
 }