cfg80211: fix in nl80211_set_reg()
There is a race on access to last_request and its alpha2
through reg_is_valid_request() and us possibly processing
first another regulatory request on another CPU. We avoid
this improbably race by locking with the cfg80211_mutex as
we should have done in the first place. While at it add
the assert on locking on reg_is_valid_request().
Cc: stable@kernel.org
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 66e0fb6..6325040 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2570,6 +2570,8 @@
return -EINVAL;
}
+ mutex_lock(&cfg80211_mutex);
+
if (!reg_is_valid_request(alpha2)) {
r = -EINVAL;
goto bad_reg;
@@ -2607,13 +2609,14 @@
BUG_ON(rule_idx != num_rules);
- mutex_lock(&cfg80211_mutex);
r = set_regdom(rd);
+
mutex_unlock(&cfg80211_mutex);
return r;
bad_reg:
+ mutex_unlock(&cfg80211_mutex);
kfree(rd);
return r;
}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 48db569..8d176a8 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -382,6 +382,8 @@
/* Used by nl80211 before kmalloc'ing our regulatory domain */
bool reg_is_valid_request(const char *alpha2)
{
+ assert_cfg80211_lock();
+
if (!last_request)
return false;