Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'mac80211-for-davem-2019-10-08' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211

Johannes Berg says:

====================
A number of fixes:
* allow scanning when operating on radar channels in
ETSI regdomains
* accept deauth frames in IBSS - we have code to parse
and handle them, but were dropping them early
* fix an allocation failure path in hwsim
* fix a failure path memory leak in nl80211 FTM code
* fix RCU handling & locking in multi-BSSID parsing
* reject malformed SSID in mac80211 (this shouldn't
really be able to happen, but defense in depth)
* avoid userspace buffer overrun in ancient wext code
if SSID was too long
====================

Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com>

+71 -27
+1 -1
drivers/net/wireless/mac80211_hwsim.c
··· 4026 4026 err = dev_alloc_name(hwsim_mon, hwsim_mon->name); 4027 4027 if (err < 0) { 4028 4028 rtnl_unlock(); 4029 - goto out_free_radios; 4029 + goto out_free_mon; 4030 4030 } 4031 4031 4032 4032 err = register_netdevice(hwsim_mon);
+8
include/net/cfg80211.h
··· 5550 5550 const char *reg_initiator_name(enum nl80211_reg_initiator initiator); 5551 5551 5552 5552 /** 5553 + * regulatory_pre_cac_allowed - check if pre-CAC allowed in the current regdom 5554 + * @wiphy: wiphy for which pre-CAC capability is checked. 5555 + * 5556 + * Pre-CAC is allowed only in some regdomains (notable ETSI). 5557 + */ 5558 + bool regulatory_pre_cac_allowed(struct wiphy *wiphy); 5559 + 5560 + /** 5553 5561 * DOC: Internal regulatory db functions 5554 5562 * 5555 5563 */
+3 -2
net/mac80211/mlme.c
··· 2633 2633 2634 2634 rcu_read_lock(); 2635 2635 ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID); 2636 - if (WARN_ON_ONCE(ssid == NULL)) 2636 + if (WARN_ONCE(!ssid || ssid[1] > IEEE80211_MAX_SSID_LEN, 2637 + "invalid SSID element (len=%d)", ssid ? ssid[1] : -1)) 2637 2638 ssid_len = 0; 2638 2639 else 2639 2640 ssid_len = ssid[1]; ··· 5234 5233 5235 5234 rcu_read_lock(); 5236 5235 ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); 5237 - if (!ssidie) { 5236 + if (!ssidie || ssidie[1] > sizeof(assoc_data->ssid)) { 5238 5237 rcu_read_unlock(); 5239 5238 kfree(assoc_data); 5240 5239 return -EINVAL;
+10 -1
net/mac80211/rx.c
··· 3467 3467 case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): 3468 3468 /* process for all: mesh, mlme, ibss */ 3469 3469 break; 3470 + case cpu_to_le16(IEEE80211_STYPE_DEAUTH): 3471 + if (is_multicast_ether_addr(mgmt->da) && 3472 + !is_broadcast_ether_addr(mgmt->da)) 3473 + return RX_DROP_MONITOR; 3474 + 3475 + /* process only for station/IBSS */ 3476 + if (sdata->vif.type != NL80211_IFTYPE_STATION && 3477 + sdata->vif.type != NL80211_IFTYPE_ADHOC) 3478 + return RX_DROP_MONITOR; 3479 + break; 3470 3480 case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): 3471 3481 case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): 3472 - case cpu_to_le16(IEEE80211_STYPE_DEAUTH): 3473 3482 case cpu_to_le16(IEEE80211_STYPE_DISASSOC): 3474 3483 if (is_multicast_ether_addr(mgmt->da) && 3475 3484 !is_broadcast_ether_addr(mgmt->da))
+28 -2
net/mac80211/scan.c
··· 520 520 return 0; 521 521 } 522 522 523 + static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata) 524 + { 525 + struct ieee80211_local *local = sdata->local; 526 + struct ieee80211_sub_if_data *sdata_iter; 527 + 528 + if (!ieee80211_is_radar_required(local)) 529 + return true; 530 + 531 + if (!regulatory_pre_cac_allowed(local->hw.wiphy)) 532 + return false; 533 + 534 + mutex_lock(&local->iflist_mtx); 535 + list_for_each_entry(sdata_iter, &local->interfaces, list) { 536 + if (sdata_iter->wdev.cac_started) { 537 + mutex_unlock(&local->iflist_mtx); 538 + return false; 539 + } 540 + } 541 + mutex_unlock(&local->iflist_mtx); 542 + 543 + return true; 544 + } 545 + 523 546 static bool ieee80211_can_scan(struct ieee80211_local *local, 524 547 struct ieee80211_sub_if_data *sdata) 525 548 { 526 - if (ieee80211_is_radar_required(local)) 549 + if (!__ieee80211_can_leave_ch(sdata)) 527 550 return false; 528 551 529 552 if (!list_empty(&local->roc_list)) ··· 653 630 654 631 lockdep_assert_held(&local->mtx); 655 632 656 - if (local->scan_req || ieee80211_is_radar_required(local)) 633 + if (local->scan_req) 634 + return -EBUSY; 635 + 636 + if (!__ieee80211_can_leave_ch(sdata)) 657 637 return -EBUSY; 658 638 659 639 if (!ieee80211_can_scan(local, sdata)) {
+1 -1
net/wireless/nl80211.c
··· 13682 13682 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, 13683 13683 NL80211_CMD_GET_FTM_RESPONDER_STATS); 13684 13684 if (!hdr) 13685 - return -ENOBUFS; 13685 + goto nla_put_failure; 13686 13686 13687 13687 if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex)) 13688 13688 goto nla_put_failure;
+1
net/wireless/reg.c
··· 3883 3883 3884 3884 return pre_cac_allowed; 3885 3885 } 3886 + EXPORT_SYMBOL(regulatory_pre_cac_allowed); 3886 3887 3887 3888 void regulatory_propagate_dfs_state(struct wiphy *wiphy, 3888 3889 struct cfg80211_chan_def *chandef,
-8
net/wireless/reg.h
··· 156 156 #define REG_PRE_CAC_EXPIRY_GRACE_MS 2000 157 157 158 158 /** 159 - * regulatory_pre_cac_allowed - if pre-CAC allowed in the current dfs domain 160 - * @wiphy: wiphy for which pre-CAC capability is checked. 161 - 162 - * Pre-CAC is allowed only in ETSI domain. 163 - */ 164 - bool regulatory_pre_cac_allowed(struct wiphy *wiphy); 165 - 166 - /** 167 159 * regulatory_propagate_dfs_state - Propagate DFS channel state to other wiphys 168 160 * @wiphy - wiphy on which radar is detected and the event will be propagated 169 161 * to other available wiphys having the same DFS domain
+13 -10
net/wireless/scan.c
··· 1703 1703 static void 1704 1704 cfg80211_update_notlisted_nontrans(struct wiphy *wiphy, 1705 1705 struct cfg80211_bss *nontrans_bss, 1706 - struct ieee80211_mgmt *mgmt, size_t len, 1707 - gfp_t gfp) 1706 + struct ieee80211_mgmt *mgmt, size_t len) 1708 1707 { 1709 1708 u8 *ie, *new_ie, *pos; 1710 1709 const u8 *nontrans_ssid, *trans_ssid, *mbssid; ··· 1713 1714 struct cfg80211_bss_ies *new_ies; 1714 1715 const struct cfg80211_bss_ies *old; 1715 1716 u8 cpy_len; 1717 + 1718 + lockdep_assert_held(&wiphy_to_rdev(wiphy)->bss_lock); 1716 1719 1717 1720 ie = mgmt->u.probe_resp.variable; 1718 1721 ··· 1732 1731 if (!mbssid || mbssid < trans_ssid) 1733 1732 return; 1734 1733 new_ie_len -= mbssid[1]; 1735 - rcu_read_lock(); 1734 + 1736 1735 nontrans_ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID); 1737 - if (!nontrans_ssid) { 1738 - rcu_read_unlock(); 1736 + if (!nontrans_ssid) 1739 1737 return; 1740 - } 1738 + 1741 1739 new_ie_len += nontrans_ssid[1]; 1742 - rcu_read_unlock(); 1743 1740 1744 1741 /* generate new ie for nontrans BSS 1745 1742 * 1. replace SSID with nontrans BSS' SSID 1746 1743 * 2. skip MBSSID IE 1747 1744 */ 1748 - new_ie = kzalloc(new_ie_len, gfp); 1745 + new_ie = kzalloc(new_ie_len, GFP_ATOMIC); 1749 1746 if (!new_ie) 1750 1747 return; 1751 - new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, gfp); 1748 + 1749 + new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, GFP_ATOMIC); 1752 1750 if (!new_ies) 1753 1751 goto out_free; 1754 1752 ··· 1901 1901 cfg80211_parse_mbssid_frame_data(wiphy, data, mgmt, len, 1902 1902 &non_tx_data, gfp); 1903 1903 1904 + spin_lock_bh(&wiphy_to_rdev(wiphy)->bss_lock); 1905 + 1904 1906 /* check if the res has other nontransmitting bss which is not 1905 1907 * in MBSSID IE 1906 1908 */ ··· 1917 1915 ies2 = rcu_access_pointer(tmp_bss->ies); 1918 1916 if (ies2->tsf < ies1->tsf) 1919 1917 cfg80211_update_notlisted_nontrans(wiphy, tmp_bss, 1920 - mgmt, len, gfp); 1918 + mgmt, len); 1921 1919 } 1920 + spin_unlock_bh(&wiphy_to_rdev(wiphy)->bss_lock); 1922 1921 1923 1922 return res; 1924 1923 }
+6 -2
net/wireless/wext-sme.c
··· 202 202 struct iw_point *data, char *ssid) 203 203 { 204 204 struct wireless_dev *wdev = dev->ieee80211_ptr; 205 + int ret = 0; 205 206 206 207 /* call only for station! */ 207 208 if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) ··· 220 219 if (ie) { 221 220 data->flags = 1; 222 221 data->length = ie[1]; 223 - memcpy(ssid, ie + 2, data->length); 222 + if (data->length > IW_ESSID_MAX_SIZE) 223 + ret = -EINVAL; 224 + else 225 + memcpy(ssid, ie + 2, data->length); 224 226 } 225 227 rcu_read_unlock(); 226 228 } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) { ··· 233 229 } 234 230 wdev_unlock(wdev); 235 231 236 - return 0; 232 + return ret; 237 233 } 238 234 239 235 int cfg80211_mgd_wext_siwap(struct net_device *dev,