summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2009-02-21 00:04:22 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-02-27 14:52:55 -0500
commit80778f18c09673df2712c7da28aa920469adcae2 (patch)
tree06bdfa7cc48aefb68e6ec9e0f03777c574372c08
parenta1794390f1afc3631ac056e0f1677b7ab6f7ee74 (diff)
nl80211: disallow user requests prior to regulatory_init()
If cfg80211 is built into the kernel there is perhaps a small time window betwen nl80211_init() and regulatory_init() where cfg80211_regdomain hasn't yet been initialized to let the wireless core do its work. During that rare case and time frame (if its even possible) we don't allow user regulatory changes as cfg80211 is working on enabling its first regulatory domain. To check for cfg80211_regdomain we now contend the entire operation using the cfg80211_mutex. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/wireless/nl80211.c34
1 files changed, 26 insertions, 8 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 88a530f707e..130fc2561ba 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1906,24 +1906,42 @@ static int nl80211_req_set_reg(struct sk_buff *skb, struct genl_info *info)
int r;
char *data = NULL;
- if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
- return -EINVAL;
+ /*
+ * You should only get this when cfg80211 hasn't yet initialized
+ * completely when built-in to the kernel right between the time
+ * window between nl80211_init() and regulatory_init(), if that is
+ * even possible.
+ */
+ mutex_lock(&cfg80211_mutex);
+ if (unlikely(!cfg80211_regdomain)) {
+ r = -EINPROGRESS;
+ goto out;
+ }
+
+ if (!info->attrs[NL80211_ATTR_REG_ALPHA2]) {
+ r = -EINVAL;
+ goto out;
+ }
data = nla_data(info->attrs[NL80211_ATTR_REG_ALPHA2]);
#ifdef CONFIG_WIRELESS_OLD_REGULATORY
/* We ignore world regdom requests with the old regdom setup */
- if (is_world_regdom(data))
- return -EINVAL;
+ if (is_world_regdom(data)) {
+ r = -EINVAL;
+ goto out;
+ }
#endif
- mutex_lock(&cfg80211_mutex);
r = __regulatory_hint(NULL, REGDOM_SET_BY_USER, data, 0, ENVIRON_ANY);
- mutex_unlock(&cfg80211_mutex);
- /* This means the regulatory domain was already set, however
+ /*
+ * This means the regulatory domain was already set, however
* we don't want to confuse userspace with a "successful error"
- * message so lets just treat it as a success */
+ * message so lets just treat it as a success
+ */
if (r == -EALREADY)
r = 0;
+out:
+ mutex_unlock(&cfg80211_mutex);
return r;
}