2013-01-09 11:19:40

by Johannes Berg

[permalink] [raw]
Subject: [PATCH] regulatory: fix restore_regulatory_settings

From: Johannes Berg <[email protected]>

My commit 379b82f4c9dc6e67bf61aa61b096c06a2f320f60
("regulatory: pass new regdomain to reset function")
broke the restore_regulatory_settings() function due
to a logic change. Consider this change:

- reset_regdomains(true);
- cfg80211_regdomain = cfg80211_world_regdom;
+ reset_regdomains(true, cfg80211_world_regdom);

This looks innocent enough, until you realise that the
called function (reset_regdomains) also resets the
cfg80211_world_regdom pointer, so that the old version
of the code would use the new object it pointed to and
the new version of the code uses the old object. This
lead to a double-free of this object.

Since reset_regdomains() sets it to &world_regdom, use
that directly.

Reported-by: Sujith Manoharan <[email protected]>
Tested-by: Sujith Manoharan <[email protected]>
Reported-by: Bob Copeland <[email protected]>
Reported-by: Emmanuel Grumbach <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
---
net/wireless/reg.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 2193f62..8c114e8 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1848,7 +1848,7 @@ static void restore_regulatory_settings(bool reset_user)
mutex_lock(&cfg80211_mutex);
mutex_lock(&reg_mutex);

- reset_regdomains(true, cfg80211_world_regdom);
+ reset_regdomains(true, &world_regdom);
restore_alpha2(alpha2, reset_user);

/*
--
1.8.0



2013-01-09 11:20:23

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH] regulatory: fix restore_regulatory_settings

On Wed, 2013-01-09 at 12:20 +0100, Johannes Berg wrote:
> From: Johannes Berg <[email protected]>
>
> My commit 379b82f4c9dc6e67bf61aa61b096c06a2f320f60
> ("regulatory: pass new regdomain to reset function")
> broke the restore_regulatory_settings() function due
> to a logic change. Consider this change:
>
> - reset_regdomains(true);
> - cfg80211_regdomain = cfg80211_world_regdom;
> + reset_regdomains(true, cfg80211_world_regdom);
>
> This looks innocent enough, until you realise that the
> called function (reset_regdomains) also resets the
> cfg80211_world_regdom pointer, so that the old version
> of the code would use the new object it pointed to and
> the new version of the code uses the old object. This
> lead to a double-free of this object.
>
> Since reset_regdomains() sets it to &world_regdom, use
> that directly.

Applied.

johannes