summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/wireless/nl80211.c18
-rw-r--r--net/wireless/reg.c21
-rw-r--r--net/wireless/reg.h1
3 files changed, 17 insertions, 23 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9c2c91845be7..b387deaf1132 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;
}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 752729ecd701..b3f94c957d1d 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -425,12 +425,16 @@ static int call_crda(const char *alpha2)
return kobject_uevent(&reg_pdev->dev.kobj, KOBJ_CHANGE);
}
-/* Used by nl80211 before kmalloc'ing our regulatory domain */
-bool reg_is_valid_request(const char *alpha2)
+static bool reg_is_valid_request(const char *alpha2)
{
+ assert_reg_lock();
+
if (!last_request)
return false;
+ if (last_request->processed)
+ return false;
+
return alpha2_equal(last_request->alpha2, alpha2);
}
@@ -1470,6 +1474,7 @@ new_request:
last_request = pending_request;
last_request->intersect = intersect;
+ last_request->processed = false;
pending_request = NULL;
@@ -2060,11 +2065,13 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
const struct ieee80211_regdomain *regd;
const struct ieee80211_regdomain *intersected_rd = NULL;
struct wiphy *request_wiphy;
+
/* Some basic sanity checks first */
+ if (!reg_is_valid_request(rd->alpha2))
+ return -EINVAL;
+
if (is_world_regdom(rd->alpha2)) {
- if (WARN_ON(!reg_is_valid_request(rd->alpha2)))
- return -EINVAL;
update_world_regdomain(rd);
return 0;
}
@@ -2073,9 +2080,6 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
!is_unknown_alpha2(rd->alpha2))
return -EINVAL;
- if (!last_request)
- return -EINVAL;
-
/*
* Lets only bother proceeding on the same alpha2 if the current
* rd is non static (it means CRDA was present and was used last)
@@ -2097,9 +2101,6 @@ static int __set_regdom(const struct ieee80211_regdomain *rd)
* internal EEPROM data
*/
- if (WARN_ON(!reg_is_valid_request(rd->alpha2)))
- return -EINVAL;
-
if (!is_valid_rd(rd)) {
pr_err("Invalid regulatory domain detected:\n");
print_regdomain_info(rd);
diff --git a/net/wireless/reg.h b/net/wireless/reg.h
index 37891e813a74..d391b50d2829 100644
--- a/net/wireless/reg.h
+++ b/net/wireless/reg.h
@@ -19,7 +19,6 @@
extern const struct ieee80211_regdomain *cfg80211_regdomain;
bool is_world_regdom(const char *alpha2);
-bool reg_is_valid_request(const char *alpha2);
bool reg_supported_dfs_region(u8 dfs_region);
int regulatory_hint_user(const char *alpha2,