All of lore.kernel.org
 help / color / mirror / Atom feed
* Memory leak in cfg80211
@ 2013-02-02 23:17 Larry Finger
  2013-02-04 17:24 ` Johannes Berg
  0 siblings, 1 reply; 5+ messages in thread
From: Larry Finger @ 2013-02-02 23:17 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

Johannes,

A recent change to cfg80211 has resulted in kmemleak reporting a new leak:

unreferenced object 0xffff8800b24cba80 (size 192):
   comm "kworker/1:0", pid 13, jiffies 4294899104 (age 5432.336s)
   hex dump (first 32 bytes):
     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
     06 00 00 00 55 53 00 00 d0 a6 24 00 40 b8 25 00  ....US....$.@.%.
   backtrace:
     [<ffffffff81444cf1>] kmemleak_alloc+0x21/0x50
     [<ffffffff81147770>] __kmalloc+0x130/0x2c0
     [<ffffffffa02b93e3>] reg_copy_regd+0x23/0xa0 [cfg80211]
     [<ffffffffa02ba5e2>] reg_todo+0x3d2/0x5a0 [cfg80211]
     [<ffffffff81063cdd>] process_one_work+0x19d/0x6f0
     [<ffffffff81064605>] worker_thread+0x155/0x400
     [<ffffffff81069b56>] kthread+0xd6/0xe0
     [<ffffffff8145ba7c>] ret_from_fork+0x7c/0xb0
     [<ffffffffffffffff>] 0xffffffffffffffff

The traceback points back to the call at line 353 of net/wireless/reg.c where 
the regd space is allocated.

I verified that the memory is still allocated after unloading cfg80211. This is 
not a false report from kmemleak.

Thanks,

Larry




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Memory leak in cfg80211
  2013-02-02 23:17 Memory leak in cfg80211 Larry Finger
@ 2013-02-04 17:24 ` Johannes Berg
  2013-02-04 17:43   ` Larry Finger
  2013-02-04 19:31   ` Larry Finger
  0 siblings, 2 replies; 5+ messages in thread
From: Johannes Berg @ 2013-02-04 17:24 UTC (permalink / raw)
  To: Larry Finger, mcgrof; +Cc: linux-wireless

Larry,

> A recent change to cfg80211 has resulted in kmemleak reporting a new leak:

Curious.

> unreferenced object 0xffff8800b24cba80 (size 192):
>    comm "kworker/1:0", pid 13, jiffies 4294899104 (age 5432.336s)
>    hex dump (first 32 bytes):
>      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
>      06 00 00 00 55 53 00 00 d0 a6 24 00 40 b8 25 00  ....US....$.@.%.
>    backtrace:
>      [<ffffffff81444cf1>] kmemleak_alloc+0x21/0x50
>      [<ffffffff81147770>] __kmalloc+0x130/0x2c0
>      [<ffffffffa02b93e3>] reg_copy_regd+0x23/0xa0 [cfg80211]
>      [<ffffffffa02ba5e2>] reg_todo+0x3d2/0x5a0 [cfg80211]
>      [<ffffffff81063cdd>] process_one_work+0x19d/0x6f0
>      [<ffffffff81064605>] worker_thread+0x155/0x400
>      [<ffffffff81069b56>] kthread+0xd6/0xe0
>      [<ffffffff8145ba7c>] ret_from_fork+0x7c/0xb0
>      [<ffffffffffffffff>] 0xffffffffffffffff
> 
> The traceback points back to the call at line 353 of net/wireless/reg.c where 
> the regd space is allocated.

Yeah. The more interesting part (I think) is reg_todo(), which seems it
really is the __regulatory_hint() function, which gets inlined.

Were you able to reproduce this? I don't think I can since my devices
(Intel) don't use wiphy->regd. If you can, maybe you could try to
dump_stack() with the pointer every time wiphy->regd gets assigned, and
also print the old value.

To me, this looks like wiphy->regd gets overwritten without freeing the
old value, but I don't see what recent (since 3.7) change should have
caused this to change behaviour. Luis?

johannes


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Memory leak in cfg80211
  2013-02-04 17:24 ` Johannes Berg
@ 2013-02-04 17:43   ` Larry Finger
  2013-02-04 19:31   ` Larry Finger
  1 sibling, 0 replies; 5+ messages in thread
From: Larry Finger @ 2013-02-04 17:43 UTC (permalink / raw)
  To: Johannes Berg; +Cc: mcgrof, linux-wireless

On 02/04/2013 11:24 AM, Johannes Berg wrote:

Johannes,

>
> Yeah. The more interesting part (I think) is reg_todo(), which seems it
> really is the __regulatory_hint() function, which gets inlined.
>
> Were you able to reproduce this? I don't think I can since my devices
> (Intel) don't use wiphy->regd. If you can, maybe you could try to
> dump_stack() with the pointer every time wiphy->regd gets assigned, and
> also print the old value.

Yes, it is reproducible. I get one for every load of ath9k_htc. Other drivers 
may also fail - that happens to be the device I'm using now.

> To me, this looks like wiphy->regd gets overwritten without freeing the
> old value, but I don't see what recent (since 3.7) change should have
> caused this to change behaviour. Luis?

I'll set that up and report back.

Larry



^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Memory leak in cfg80211
  2013-02-04 17:24 ` Johannes Berg
  2013-02-04 17:43   ` Larry Finger
@ 2013-02-04 19:31   ` Larry Finger
  2013-02-04 20:56     ` Johannes Berg
  1 sibling, 1 reply; 5+ messages in thread
From: Larry Finger @ 2013-02-04 19:31 UTC (permalink / raw)
  To: Johannes Berg; +Cc: mcgrof, linux-wireless

Johannes,

You got it right. I got two tracebacks as follows:

[   22.147978] cfg80211: wiphy->regd changed at line 1459: old           (null), 
new: ffff8800b1e25a80
[   22.147982] Pid: 292, comm: kworker/1:1 Not tainted 3.8.0-rc6-wl+ #96
[   22.147985] Call Trace:
[   22.148032]  [<ffffffffa03c6623>] reg_todo+0x403/0x5e0 [cfg80211]
[   22.148088]  [<ffffffff81063cdd>] process_one_work+0x19d/0x6f0
[   22.148098]  [<ffffffff81063c70>] ? process_one_work+0x130/0x6f0
[   22.148103]  [<ffffffff810ba840>] ? cgroup_path+0x170/0x170
[   22.148120]  [<ffffffffa03c6220>] ? regdom_changes+0x50/0x50 [cfg80211]
[   22.148128]  [<ffffffff81064605>] worker_thread+0x155/0x400
[   22.148134]  [<ffffffff810a568d>] ? trace_hardirqs_on+0xd/0x10
[   22.148139]  [<ffffffff810644b0>] ? rescuer_thread+0x240/0x240
[   22.148144]  [<ffffffff81069b56>] kthread+0xd6/0xe0
[   22.148150]  [<ffffffff8145acab>] ? _raw_spin_unlock_irq+0x2b/0x50
[   22.148155]  [<ffffffff81069a80>] ? __init_kthread_worker+0x70/0x70
[   22.148160]  [<ffffffff8145ba7c>] ret_from_fork+0x7c/0xb0
[   22.148164]  [<ffffffff81069a80>] ? __init_kthread_worker+0x70/0x70
[   22.148169] cfg80211: Calling CRDA for country: CN


[   22.161223] cfg80211: request_wiphy->regd changed at line 2199: old 
ffff8800b1e25a80, new: ffff8800b61c66c0
[   22.161230] Pid: 2377, comm: crda Not tainted 3.8.0-rc6-wl+ #96
[   22.161233] Call Trace:
[   22.161275]  [<ffffffffa03c76fc>] set_regdom+0x6dc/0x750 [cfg80211]
[   22.161293]  [<ffffffffa03d1f56>] nl80211_set_reg+0x236/0x2a0 [cfg80211]
[   22.161302]  [<ffffffff813d2e24>] genl_rcv_msg+0x274/0x2b0
[   22.161306]  [<ffffffff813d2bb0>] ? genl_rcv+0x30/0x30
[   22.161311]  [<ffffffff813d20b9>] netlink_rcv_skb+0xa9/0xc0
[   22.161315]  [<ffffffff813d2ba0>] genl_rcv+0x20/0x30
[   22.161319]  [<ffffffff813d1a0b>] netlink_unicast+0x19b/0x220
[   22.161324]  [<ffffffff813d1e76>] netlink_sendmsg+0x336/0x3b0
[   22.161329]  [<ffffffff81390b17>] sock_sendmsg+0x87/0xa0
[   22.161335]  [<ffffffff81127aa7>] ? might_fault+0x57/0xb0
[   22.161340]  [<ffffffff81390fcc>] __sys_sendmsg+0x37c/0x390
[   22.161345]  [<ffffffff8106f9be>] ? up_read+0x1e/0x40
[   22.161350]  [<ffffffff81033b3c>] ? __do_page_fault+0x1fc/0x500
[   22.161356]  [<ffffffff8116f1aa>] ? fget_light+0x3da/0x4d0
[   22.161359]  [<ffffffff81393f08>] ? sys_getsockname+0xb8/0xc0
[   22.161363]  [<ffffffff813944e4>] sys_sendmsg+0x44/0x80
[   22.161368]  [<ffffffff8145bb29>] system_call_fastpath+0x16/0x1b

The second one replaced a non-NULL pointer, and kmemleak confirms that it is the 
leaked block.

larrylap:~ # cat /sys/kernel/debug/kmemleak
unreferenced object 0xffff8800b1e25a80 (size 192):
   comm "kworker/1:1", pid 292, jiffies 4294897832 (age 3645.856s)
   hex dump (first 32 bytes):
     00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
     06 00 00 00 55 53 00 00 d0 a6 24 00 40 b8 25 00  ....US....$.@.%.
   backtrace:
     [<ffffffff81444cf1>] kmemleak_alloc+0x21/0x50
     [<ffffffff81147770>] __kmalloc+0x130/0x2c0
     [<ffffffffa03c5473>] reg_copy_regd+0x23/0xa0 [cfg80211]
     [<ffffffffa03c65f2>] reg_todo+0x3d2/0x5e0 [cfg80211]
     [<ffffffff81063cdd>] process_one_work+0x19d/0x6f0
     [<ffffffff81064605>] worker_thread+0x155/0x400
     [<ffffffff81069b56>] kthread+0xd6/0xe0
     [<ffffffff8145ba7c>] ret_from_fork+0x7c/0xb0
     [<ffffffffffffffff>] 0xffffffffffffffff
larrylap:~ #

This leak seems to occur because I am loading cfg80211 with the regdom set to 
"US"; however, the driver is forcing "CN". That is my penalty for buying the 
adapter on Ebay; however, I think my setting should override that of the driver, 
which might be a separate bug. I'm OK as long as there are no FCC inspectors in 
my neighborhood to see that I am sending out probes on channels 12 and 13.

I am only vaguely familiar with the rcu routines. Is it sufficient to do the 
simple kfree() before the rcu_assign_pointer() call, or is it necessary to make 
an rcu_lock() call as well? If a simple kfree() is all that is needed, then the 
following patch should be OK. If is is, I'll do some testing and do a proper 
submission later:

Index: wireless-testing-new/net/wireless/reg.c
===================================================================
--- wireless-testing-new.orig/net/wireless/reg.c
+++ wireless-testing-new/net/wireless/reg.c
@@ -2189,10 +2189,12 @@ static int __set_regdom(const struct iee
                  * However if a driver requested this specific regulatory
                  * domain we keep it for its private use
                  */
-               if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER)
+               if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
+                       kfree(request_wiphy->regd);
                         rcu_assign_pointer(request_wiphy->regd, rd);
-               else
+               } else {
                         kfree(rd);
+               }

                 rd = NULL;

Larry


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: Memory leak in cfg80211
  2013-02-04 19:31   ` Larry Finger
@ 2013-02-04 20:56     ` Johannes Berg
  0 siblings, 0 replies; 5+ messages in thread
From: Johannes Berg @ 2013-02-04 20:56 UTC (permalink / raw)
  To: Larry Finger; +Cc: mcgrof, linux-wireless

Larry,

> You got it right. I got two tracebacks as follows:
> 
> [   22.147978] cfg80211: wiphy->regd changed at line 1459: old           (null), new: ffff8800b1e25a80
> [   22.147982] Pid: 292, comm: kworker/1:1 Not tainted 3.8.0-rc6-wl+ #96
> [   22.147985] Call Trace:
> [   22.148032]  [<ffffffffa03c6623>] reg_todo+0x403/0x5e0 [cfg80211]
> [   22.148088]  [<ffffffff81063cdd>] process_one_work+0x19d/0x6f0

> [   22.161223] cfg80211: request_wiphy->regd changed at line 2199: old ffff8800b1e25a80, new: ffff8800b61c66c0
> [   22.161230] Pid: 2377, comm: crda Not tainted 3.8.0-rc6-wl+ #96
> [   22.161233] Call Trace:
> [   22.161275]  [<ffffffffa03c76fc>] set_regdom+0x6dc/0x750 [cfg80211]
> [   22.161293]  [<ffffffffa03d1f56>] nl80211_set_reg+0x236/0x2a0 [cfg80211]

> The second one replaced a non-NULL pointer, and kmemleak confirms that it is the 
> leaked block.

Ok, good. I'm not sure how a recent change would have caused this
though, but I'm sure we can fix it :)

> This leak seems to occur because I am loading cfg80211 with the regdom set to 
> "US"; however, the driver is forcing "CN". That is my penalty for buying the 
> adapter on Ebay; however, I think my setting should override that of the driver, 
> which might be a separate bug. I'm OK as long as there are no FCC inspectors in 
> my neighborhood to see that I am sending out probes on channels 12 and 13.

:)
That might indeed be a different bug.

> I am only vaguely familiar with the rcu routines. Is it sufficient to do the 
> simple kfree() before the rcu_assign_pointer() call, or is it necessary to make 
> an rcu_lock() call as well? If a simple kfree() is all that is needed, then the 
> following patch should be OK. If is is, I'll do some testing and do a proper 
> submission later:

No, neither is quite right, another thread might be accessing it at the
same time.

> Index: wireless-testing-new/net/wireless/reg.c
> ===================================================================
> --- wireless-testing-new.orig/net/wireless/reg.c
> +++ wireless-testing-new/net/wireless/reg.c
> @@ -2189,10 +2189,12 @@ static int __set_regdom(const struct iee
>                   * However if a driver requested this specific regulatory
>                   * domain we keep it for its private use
>                   */
> -               if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER)
> +               if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER) {
> +                       kfree(request_wiphy->regd);

This one should be rcu_free_regdom(), except you also need a temporary
variable:

	tmp = get_wiphy_regdom(request_wiphy);
	rcu_assign_pointer(request_wiphy->regd, rd);
	rcu_free_regdom(tmp);

Note this also works if "tmp" ends up NULL.

johannes


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2013-02-04 20:56 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-02-02 23:17 Memory leak in cfg80211 Larry Finger
2013-02-04 17:24 ` Johannes Berg
2013-02-04 17:43   ` Larry Finger
2013-02-04 19:31   ` Larry Finger
2013-02-04 20:56     ` Johannes Berg

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.