summaryrefslogtreecommitdiff
path: root/net/wireless/nl80211.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-12-03 23:48:59 (GMT)
committerJohannes Berg <johannes.berg@intel.com>2013-01-03 12:01:28 (GMT)
commit6913b49a5071064f49f7a74b432286fa735f7612 (patch)
tree15b54b8dd9d5eef07e8a9366b3f9e391043499f1 /net/wireless/nl80211.c
parent540f6f2cc545da9ae2baa9faa3152fc550bedb57 (diff)
downloadlinux-fsl-qoriq-6913b49a5071064f49f7a74b432286fa735f7612.tar.xz
regulatory: fix reg_is_valid_request handling
There's a bug with the world regulatory domain, it can be updated any time which is different from all other regdomains that can only be updated once after a request for them. Fix this by adding a check for "processed" to the reg_is_valid_request() function and clear that when doing a request. While looking at this I also found another locking bug, last_request is protected by the reg_mutex not the cfg80211_mutex so the code in nl80211 is racy. Remove that code as it only tries to prevent an allocation in an error case, which isn't necessary. Then the function can also become static and locking in nl80211 can have a smaller scope. Also change __set_regdom() to do the checks earlier and not different for world/other regdomains. Acked-by: Luis R. Rodriguez <mcgrof@do-not-panic.com> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless/nl80211.c')
-rw-r--r--net/wireless/nl80211.c18
1 files changed, 6 insertions, 12 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9c2c918..b387dea 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -4265,21 +4265,12 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
- mutex_lock(&cfg80211_mutex);
-
- if (!reg_is_valid_request(alpha2)) {
- r = -EINVAL;
- goto bad_reg;
- }
-
size_of_regd = sizeof(struct ieee80211_regdomain) +
num_rules * sizeof(struct ieee80211_reg_rule);
rd = kzalloc(size_of_regd, GFP_KERNEL);
- if (!rd) {
- r = -ENOMEM;
- goto bad_reg;
- }
+ if (!rd)
+ return -ENOMEM;
rd->n_reg_rules = num_rules;
rd->alpha2[0] = alpha2[0];
@@ -4309,11 +4300,14 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
}
}
+ mutex_lock(&cfg80211_mutex);
+
r = set_regdom(rd);
+ /* set_regdom took ownership */
rd = NULL;
+ mutex_unlock(&cfg80211_mutex);
bad_reg:
- mutex_unlock(&cfg80211_mutex);
kfree(rd);
return r;
}