aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2011-04-05 13:49:03 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-04-07 15:52:29 -0400
commit146095557b01cf5ff5d66554d96cbb8133d94eb9 (patch)
tree38c92011c76c8a9510ea4cd1a02192113a9ddc7c /net
parent02a7fa00a6d145037d549c779ad7692deb504acc (diff)
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: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/wireless/reg.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 3332d5bce317..7b1a89b20ebf 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1744,6 +1744,8 @@ static void restore_regulatory_settings(bool reset_user)
1744{ 1744{
1745 char alpha2[2]; 1745 char alpha2[2];
1746 struct reg_beacon *reg_beacon, *btmp; 1746 struct reg_beacon *reg_beacon, *btmp;
1747 struct regulatory_request *reg_request, *tmp;
1748 LIST_HEAD(tmp_reg_req_list);
1747 1749
1748 mutex_lock(&cfg80211_mutex); 1750 mutex_lock(&cfg80211_mutex);
1749 mutex_lock(&reg_mutex); 1751 mutex_lock(&reg_mutex);
@@ -1751,6 +1753,25 @@ static void restore_regulatory_settings(bool reset_user)
1751 reset_regdomains(); 1753 reset_regdomains();
1752 restore_alpha2(alpha2, reset_user); 1754 restore_alpha2(alpha2, reset_user);
1753 1755
1756 /*
1757 * If there's any pending requests we simply
1758 * stash them to a temporary pending queue and
1759 * add then after we've restored regulatory
1760 * settings.
1761 */
1762 spin_lock(&reg_requests_lock);
1763 if (!list_empty(&reg_requests_list)) {
1764 list_for_each_entry_safe(reg_request, tmp,
1765 &reg_requests_list, list) {
1766 if (reg_request->initiator !=
1767 NL80211_REGDOM_SET_BY_USER)
1768 continue;
1769 list_del(&reg_request->list);
1770 list_add_tail(&reg_request->list, &tmp_reg_req_list);
1771 }
1772 }
1773 spin_unlock(&reg_requests_lock);
1774
1754 /* Clear beacon hints */ 1775 /* Clear beacon hints */
1755 spin_lock_bh(&reg_pending_beacons_lock); 1776 spin_lock_bh(&reg_pending_beacons_lock);
1756 if (!list_empty(&reg_pending_beacons)) { 1777 if (!list_empty(&reg_pending_beacons)) {
@@ -1785,8 +1806,31 @@ static void restore_regulatory_settings(bool reset_user)
1785 */ 1806 */
1786 if (is_an_alpha2(alpha2)) 1807 if (is_an_alpha2(alpha2))
1787 regulatory_hint_user(user_alpha2); 1808 regulatory_hint_user(user_alpha2);
1788}
1789 1809
1810 if (list_empty(&tmp_reg_req_list))
1811 return;
1812
1813 mutex_lock(&cfg80211_mutex);
1814 mutex_lock(&reg_mutex);
1815
1816 spin_lock(&reg_requests_lock);
1817 list_for_each_entry_safe(reg_request, tmp, &tmp_reg_req_list, list) {
1818 REG_DBG_PRINT("Adding request for country %c%c back "
1819 "into the queue\n",
1820 reg_request->alpha2[0],
1821 reg_request->alpha2[1]);
1822 list_del(&reg_request->list);
1823 list_add_tail(&reg_request->list, &reg_requests_list);
1824 }
1825 spin_unlock(&reg_requests_lock);
1826
1827 mutex_unlock(&reg_mutex);
1828 mutex_unlock(&cfg80211_mutex);
1829
1830 REG_DBG_PRINT("Kicking the queue\n");
1831
1832 schedule_work(&reg_work);
1833}
1790 1834
1791void regulatory_hint_disconnect(void) 1835void regulatory_hint_disconnect(void)
1792{ 1836{