Commit 14609555 authored by Luis R. Rodriguez's avatar Luis R. Rodriguez Committed by John W. Linville

cfg80211: fix regulatory restore upon user hints

When we restore regulatory settings its possible CRDA
will not reply because of a bogus user entry. In this
case the bogus entry will prevent any further processing
on cfg80211 for regulatory domains even if we restore
regulatory settings.

To prevent this we suck out all pending requests when
restoring regulatory settings and add them back into the
queue after we have queued up the reset work.

The impact of not having this applied is that a user
with privileges can issue a userspace regulatory hint
while we are disasocciating and this would prevent any
further processing of regulatory domains.
Signed-off-by: default avatarLuis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 02a7fa00
...@@ -1744,6 +1744,8 @@ static void restore_regulatory_settings(bool reset_user) ...@@ -1744,6 +1744,8 @@ static void restore_regulatory_settings(bool reset_user)
{ {
char alpha2[2]; char alpha2[2];
struct reg_beacon *reg_beacon, *btmp; struct reg_beacon *reg_beacon, *btmp;
struct regulatory_request *reg_request, *tmp;
LIST_HEAD(tmp_reg_req_list);
mutex_lock(&cfg80211_mutex); mutex_lock(&cfg80211_mutex);
mutex_lock(&reg_mutex); mutex_lock(&reg_mutex);
...@@ -1751,6 +1753,25 @@ static void restore_regulatory_settings(bool reset_user) ...@@ -1751,6 +1753,25 @@ static void restore_regulatory_settings(bool reset_user)
reset_regdomains(); reset_regdomains();
restore_alpha2(alpha2, reset_user); restore_alpha2(alpha2, reset_user);
/*
* If there's any pending requests we simply
* stash them to a temporary pending queue and
* add then after we've restored regulatory
* settings.
*/
spin_lock(&reg_requests_lock);
if (!list_empty(&reg_requests_list)) {
list_for_each_entry_safe(reg_request, tmp,
&reg_requests_list, list) {
if (reg_request->initiator !=
NL80211_REGDOM_SET_BY_USER)
continue;
list_del(&reg_request->list);
list_add_tail(&reg_request->list, &tmp_reg_req_list);
}
}
spin_unlock(&reg_requests_lock);
/* Clear beacon hints */ /* Clear beacon hints */
spin_lock_bh(&reg_pending_beacons_lock); spin_lock_bh(&reg_pending_beacons_lock);
if (!list_empty(&reg_pending_beacons)) { if (!list_empty(&reg_pending_beacons)) {
...@@ -1785,8 +1806,31 @@ static void restore_regulatory_settings(bool reset_user) ...@@ -1785,8 +1806,31 @@ static void restore_regulatory_settings(bool reset_user)
*/ */
if (is_an_alpha2(alpha2)) if (is_an_alpha2(alpha2))
regulatory_hint_user(user_alpha2); regulatory_hint_user(user_alpha2);
}
if (list_empty(&tmp_reg_req_list))
return;
mutex_lock(&cfg80211_mutex);
mutex_lock(&reg_mutex);
spin_lock(&reg_requests_lock);
list_for_each_entry_safe(reg_request, tmp, &tmp_reg_req_list, list) {
REG_DBG_PRINT("Adding request for country %c%c back "
"into the queue\n",
reg_request->alpha2[0],
reg_request->alpha2[1]);
list_del(&reg_request->list);
list_add_tail(&reg_request->list, &reg_requests_list);
}
spin_unlock(&reg_requests_lock);
mutex_unlock(&reg_mutex);
mutex_unlock(&cfg80211_mutex);
REG_DBG_PRINT("Kicking the queue\n");
schedule_work(&reg_work);
}
void regulatory_hint_disconnect(void) void regulatory_hint_disconnect(void)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment