git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
cfg80211: fix potential deadlock in regulatory
[pandora-kernel.git]
/
net
/
wireless
/
reg.c
diff --git
a/net/wireless/reg.c
b/net/wireless/reg.c
index
e71f5a6
..
d57d05b
100644
(file)
--- a/
net/wireless/reg.c
+++ b/
net/wireless/reg.c
@@
-57,8
+57,17
@@
#define REG_DBG_PRINT(args...)
#endif
#define REG_DBG_PRINT(args...)
#endif
+static struct regulatory_request core_request_world = {
+ .initiator = NL80211_REGDOM_SET_BY_CORE,
+ .alpha2[0] = '0',
+ .alpha2[1] = '0',
+ .intersect = false,
+ .processed = true,
+ .country_ie_env = ENVIRON_ANY,
+};
+
/* Receipt of information from last regulatory request */
/* Receipt of information from last regulatory request */
-static struct regulatory_request *last_request;
+static struct regulatory_request *last_request
= &core_request_world
;
/* To trigger userspace events */
static struct platform_device *reg_pdev;
/* To trigger userspace events */
static struct platform_device *reg_pdev;
@@
-150,7
+159,7
@@
static char user_alpha2[2];
module_param(ieee80211_regdom, charp, 0444);
MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
module_param(ieee80211_regdom, charp, 0444);
MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code");
-static void reset_regdomains(
void
)
+static void reset_regdomains(
bool full_reset
)
{
/* avoid freeing static information or freeing something twice */
if (cfg80211_regdomain == cfg80211_world_regdom)
{
/* avoid freeing static information or freeing something twice */
if (cfg80211_regdomain == cfg80211_world_regdom)
@@
-165,6
+174,13
@@
static void reset_regdomains(void)
cfg80211_world_regdom = &world_regdom;
cfg80211_regdomain = NULL;
cfg80211_world_regdom = &world_regdom;
cfg80211_regdomain = NULL;
+
+ if (!full_reset)
+ return;
+
+ if (last_request != &core_request_world)
+ kfree(last_request);
+ last_request = &core_request_world;
}
/*
}
/*
@@
-175,7
+191,7
@@
static void update_world_regdomain(const struct ieee80211_regdomain *rd)
{
BUG_ON(!last_request);
{
BUG_ON(!last_request);
- reset_regdomains();
+ reset_regdomains(
false
);
cfg80211_world_regdom = rd;
cfg80211_regdomain = rd;
cfg80211_world_regdom = rd;
cfg80211_regdomain = rd;
@@
-363,7
+379,15
@@
static void reg_regdb_query(const char *alpha2)
schedule_work(®_regdb_work);
}
schedule_work(®_regdb_work);
}
+
+/* Feel free to add any other sanity checks here */
+static void reg_regdb_size_check(void)
+{
+ /* We should ideally BUILD_BUG_ON() but then random builds would fail */
+ WARN_ONCE(!reg_regdb_size, "db.txt is empty, you should update it...");
+}
#else
#else
+static inline void reg_regdb_size_check(void) {}
static inline void reg_regdb_query(const char *alpha2) {}
#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
static inline void reg_regdb_query(const char *alpha2) {}
#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
@@
-1345,7
+1369,7
@@
static void reg_set_request_processed(void)
spin_unlock(®_requests_lock);
if (last_request->initiator == NL80211_REGDOM_SET_BY_USER)
spin_unlock(®_requests_lock);
if (last_request->initiator == NL80211_REGDOM_SET_BY_USER)
- cancel_delayed_work
_sync
(®_timeout);
+ cancel_delayed_work(®_timeout);
if (need_more_processing)
schedule_work(®_work);
if (need_more_processing)
schedule_work(®_work);
@@
-1407,7
+1431,8
@@
static int __regulatory_hint(struct wiphy *wiphy,
}
new_request:
}
new_request:
- kfree(last_request);
+ if (last_request != &core_request_world)
+ kfree(last_request);
last_request = pending_request;
last_request->intersect = intersect;
last_request = pending_request;
last_request->intersect = intersect;
@@
-1577,9
+1602,6
@@
static int regulatory_hint_core(const char *alpha2)
{
struct regulatory_request *request;
{
struct regulatory_request *request;
- kfree(last_request);
- last_request = NULL;
-
request = kzalloc(sizeof(struct regulatory_request),
GFP_KERNEL);
if (!request)
request = kzalloc(sizeof(struct regulatory_request),
GFP_KERNEL);
if (!request)
@@
-1777,7
+1799,7
@@
static void restore_regulatory_settings(bool reset_user)
mutex_lock(&cfg80211_mutex);
mutex_lock(®_mutex);
mutex_lock(&cfg80211_mutex);
mutex_lock(®_mutex);
- reset_regdomains();
+ reset_regdomains(
true
);
restore_alpha2(alpha2, reset_user);
/*
restore_alpha2(alpha2, reset_user);
/*
@@
-2037,12
+2059,18
@@
static int __set_regdom(const struct ieee80211_regdomain *rd)
}
request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
}
request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
+ if (!request_wiphy &&
+ (last_request->initiator == NL80211_REGDOM_SET_BY_DRIVER ||
+ last_request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
+ schedule_delayed_work(®_timeout, 0);
+ return -ENODEV;
+ }
if (!last_request->intersect) {
int r;
if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) {
if (!last_request->intersect) {
int r;
if (last_request->initiator != NL80211_REGDOM_SET_BY_DRIVER) {
- reset_regdomains();
+ reset_regdomains(
false
);
cfg80211_regdomain = rd;
return 0;
}
cfg80211_regdomain = rd;
return 0;
}
@@
-2063,7
+2091,7
@@
static int __set_regdom(const struct ieee80211_regdomain *rd)
if (r)
return r;
if (r)
return r;
- reset_regdomains();
+ reset_regdomains(
false
);
cfg80211_regdomain = rd;
return 0;
}
cfg80211_regdomain = rd;
return 0;
}
@@
-2088,7
+2116,7
@@
static int __set_regdom(const struct ieee80211_regdomain *rd)
rd = NULL;
rd = NULL;
- reset_regdomains();
+ reset_regdomains(
false
);
cfg80211_regdomain = intersected_rd;
return 0;
cfg80211_regdomain = intersected_rd;
return 0;
@@
-2108,7
+2136,7
@@
static int __set_regdom(const struct ieee80211_regdomain *rd)
kfree(rd);
rd = NULL;
kfree(rd);
rd = NULL;
- reset_regdomains();
+ reset_regdomains(
false
);
cfg80211_regdomain = intersected_rd;
return 0;
cfg80211_regdomain = intersected_rd;
return 0;
@@
-2216,6
+2244,8
@@
int __init regulatory_init(void)
spin_lock_init(®_requests_lock);
spin_lock_init(®_pending_beacons_lock);
spin_lock_init(®_requests_lock);
spin_lock_init(®_pending_beacons_lock);
+ reg_regdb_size_check();
+
cfg80211_regdomain = cfg80211_world_regdom;
user_alpha2[0] = '9';
cfg80211_regdomain = cfg80211_world_regdom;
user_alpha2[0] = '9';
@@
-2261,11
+2291,8
@@
void /* __init_or_exit */ regulatory_exit(void)
mutex_lock(&cfg80211_mutex);
mutex_lock(®_mutex);
mutex_lock(&cfg80211_mutex);
mutex_lock(®_mutex);
- reset_regdomains();
-
- kfree(last_request);
+ reset_regdomains(true);
- last_request = NULL;
dev_set_uevent_suppress(®_pdev->dev, true);
platform_device_unregister(reg_pdev);
dev_set_uevent_suppress(®_pdev->dev, true);
platform_device_unregister(reg_pdev);