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
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAl2cf4YACgkQB8qZga/f
 l8T+FA/+J4yDjue4Zw1cX8jgBr3+8l2+5sJIs59rGAcR30HYHtQvkaq4UrOy3kJ+
 w4zB2lqMIeMA/tT3+OaTLF2ELz1lBN5VqZ4fnNguFuYDOkNjzkZwQCe51z6gMwrW
 xk3dxLJz+QCDO7GF3nQer0VFBChL7fVdlIYyEoq/obwYylOUqyRGxtXa8yIaxaEe
 xE7OK67g8rVVestOGO+i/7F/ZJ6DX0hQ0ounWRoa1tTHvGjInD7t2qu69n6/66zO
 5AIVbDXGaQ+Eegk54jlJcJKQI367WNpRqOJ2HUonkoAKWID8kxbp8LLWne3DqC9i
 Ffmme2/johrGSlvgPBUCV9SUmxulQnf8vpt8mKMh2Po+1mLInFltPSPckkpoe12S
 5ps47miIZQDnVEfaojG7I2LMlfSYM1olBkAQqcqiizMISn4AYvu8H0NXJBJXV+7j
 ezgcyPCi9x2wWYy2KhKsoXPzHo8cdRUT0HbmQUe4zUXIhrlH7CZHHhkgnzR04Qz5
 Mh1TWnKr1RJEC5sua1cVDeEBXyjJDfUI+zRuq6jIvWIya+QEQ0ZWUkdjTtLFIJkY
 89e932SuHsUFEYqYYebyDnUQ7q8ZNGPVNpfC7/CTnU/T/uJoTFYDsB6ocmK3k9Cn
 4AFC/EBXD4WAl2FXDdUdAMPyLLxQwc9AxJlXMq1LOyCIvQDGopY=
 =k685
 -----END PGP SIGNATURE-----

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>
This commit is contained in:
Jakub Kicinski 2019-10-08 19:31:01 -07:00
commit a17fd2cf2d
10 changed files with 71 additions and 27 deletions

View File

@ -4026,7 +4026,7 @@ static int __init init_mac80211_hwsim(void)
err = dev_alloc_name(hwsim_mon, hwsim_mon->name); err = dev_alloc_name(hwsim_mon, hwsim_mon->name);
if (err < 0) { if (err < 0) {
rtnl_unlock(); rtnl_unlock();
goto out_free_radios; goto out_free_mon;
} }
err = register_netdevice(hwsim_mon); err = register_netdevice(hwsim_mon);

View File

@ -5549,6 +5549,14 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy,
*/ */
const char *reg_initiator_name(enum nl80211_reg_initiator initiator); const char *reg_initiator_name(enum nl80211_reg_initiator initiator);
/**
* regulatory_pre_cac_allowed - check if pre-CAC allowed in the current regdom
* @wiphy: wiphy for which pre-CAC capability is checked.
*
* Pre-CAC is allowed only in some regdomains (notable ETSI).
*/
bool regulatory_pre_cac_allowed(struct wiphy *wiphy);
/** /**
* DOC: Internal regulatory db functions * DOC: Internal regulatory db functions
* *

View File

@ -2633,7 +2633,8 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
rcu_read_lock(); rcu_read_lock();
ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID); ssid = ieee80211_bss_get_ie(cbss, WLAN_EID_SSID);
if (WARN_ON_ONCE(ssid == NULL)) if (WARN_ONCE(!ssid || ssid[1] > IEEE80211_MAX_SSID_LEN,
"invalid SSID element (len=%d)", ssid ? ssid[1] : -1))
ssid_len = 0; ssid_len = 0;
else else
ssid_len = ssid[1]; ssid_len = ssid[1];
@ -5233,7 +5234,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
rcu_read_lock(); rcu_read_lock();
ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID); ssidie = ieee80211_bss_get_ie(req->bss, WLAN_EID_SSID);
if (!ssidie) { if (!ssidie || ssidie[1] > sizeof(assoc_data->ssid)) {
rcu_read_unlock(); rcu_read_unlock();
kfree(assoc_data); kfree(assoc_data);
return -EINVAL; return -EINVAL;

View File

@ -3467,9 +3467,18 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
/* process for all: mesh, mlme, ibss */ /* process for all: mesh, mlme, ibss */
break; break;
case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
if (is_multicast_ether_addr(mgmt->da) &&
!is_broadcast_ether_addr(mgmt->da))
return RX_DROP_MONITOR;
/* process only for station/IBSS */
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
sdata->vif.type != NL80211_IFTYPE_ADHOC)
return RX_DROP_MONITOR;
break;
case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
case cpu_to_le16(IEEE80211_STYPE_DISASSOC): case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
if (is_multicast_ether_addr(mgmt->da) && if (is_multicast_ether_addr(mgmt->da) &&
!is_broadcast_ether_addr(mgmt->da)) !is_broadcast_ether_addr(mgmt->da))

View File

@ -520,10 +520,33 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local,
return 0; return 0;
} }
static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
struct ieee80211_sub_if_data *sdata_iter;
if (!ieee80211_is_radar_required(local))
return true;
if (!regulatory_pre_cac_allowed(local->hw.wiphy))
return false;
mutex_lock(&local->iflist_mtx);
list_for_each_entry(sdata_iter, &local->interfaces, list) {
if (sdata_iter->wdev.cac_started) {
mutex_unlock(&local->iflist_mtx);
return false;
}
}
mutex_unlock(&local->iflist_mtx);
return true;
}
static bool ieee80211_can_scan(struct ieee80211_local *local, static bool ieee80211_can_scan(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata) struct ieee80211_sub_if_data *sdata)
{ {
if (ieee80211_is_radar_required(local)) if (!__ieee80211_can_leave_ch(sdata))
return false; return false;
if (!list_empty(&local->roc_list)) if (!list_empty(&local->roc_list))
@ -630,7 +653,10 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
lockdep_assert_held(&local->mtx); lockdep_assert_held(&local->mtx);
if (local->scan_req || ieee80211_is_radar_required(local)) if (local->scan_req)
return -EBUSY;
if (!__ieee80211_can_leave_ch(sdata))
return -EBUSY; return -EBUSY;
if (!ieee80211_can_scan(local, sdata)) { if (!ieee80211_can_scan(local, sdata)) {

View File

@ -13682,7 +13682,7 @@ static int nl80211_get_ftm_responder_stats(struct sk_buff *skb,
hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
NL80211_CMD_GET_FTM_RESPONDER_STATS); NL80211_CMD_GET_FTM_RESPONDER_STATS);
if (!hdr) if (!hdr)
return -ENOBUFS; goto nla_put_failure;
if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex)) if (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex))
goto nla_put_failure; goto nla_put_failure;

View File

@ -3883,6 +3883,7 @@ bool regulatory_pre_cac_allowed(struct wiphy *wiphy)
return pre_cac_allowed; return pre_cac_allowed;
} }
EXPORT_SYMBOL(regulatory_pre_cac_allowed);
void regulatory_propagate_dfs_state(struct wiphy *wiphy, void regulatory_propagate_dfs_state(struct wiphy *wiphy,
struct cfg80211_chan_def *chandef, struct cfg80211_chan_def *chandef,

View File

@ -155,14 +155,6 @@ bool regulatory_indoor_allowed(void);
*/ */
#define REG_PRE_CAC_EXPIRY_GRACE_MS 2000 #define REG_PRE_CAC_EXPIRY_GRACE_MS 2000
/**
* regulatory_pre_cac_allowed - if pre-CAC allowed in the current dfs domain
* @wiphy: wiphy for which pre-CAC capability is checked.
* Pre-CAC is allowed only in ETSI domain.
*/
bool regulatory_pre_cac_allowed(struct wiphy *wiphy);
/** /**
* regulatory_propagate_dfs_state - Propagate DFS channel state to other wiphys * regulatory_propagate_dfs_state - Propagate DFS channel state to other wiphys
* @wiphy - wiphy on which radar is detected and the event will be propagated * @wiphy - wiphy on which radar is detected and the event will be propagated

View File

@ -1703,8 +1703,7 @@ cfg80211_parse_mbssid_frame_data(struct wiphy *wiphy,
static void static void
cfg80211_update_notlisted_nontrans(struct wiphy *wiphy, cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
struct cfg80211_bss *nontrans_bss, struct cfg80211_bss *nontrans_bss,
struct ieee80211_mgmt *mgmt, size_t len, struct ieee80211_mgmt *mgmt, size_t len)
gfp_t gfp)
{ {
u8 *ie, *new_ie, *pos; u8 *ie, *new_ie, *pos;
const u8 *nontrans_ssid, *trans_ssid, *mbssid; const u8 *nontrans_ssid, *trans_ssid, *mbssid;
@ -1715,6 +1714,8 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
const struct cfg80211_bss_ies *old; const struct cfg80211_bss_ies *old;
u8 cpy_len; u8 cpy_len;
lockdep_assert_held(&wiphy_to_rdev(wiphy)->bss_lock);
ie = mgmt->u.probe_resp.variable; ie = mgmt->u.probe_resp.variable;
new_ie_len = ielen; new_ie_len = ielen;
@ -1731,23 +1732,22 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy,
if (!mbssid || mbssid < trans_ssid) if (!mbssid || mbssid < trans_ssid)
return; return;
new_ie_len -= mbssid[1]; new_ie_len -= mbssid[1];
rcu_read_lock();
nontrans_ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID); nontrans_ssid = ieee80211_bss_get_ie(nontrans_bss, WLAN_EID_SSID);
if (!nontrans_ssid) { if (!nontrans_ssid)
rcu_read_unlock();
return; return;
}
new_ie_len += nontrans_ssid[1]; new_ie_len += nontrans_ssid[1];
rcu_read_unlock();
/* generate new ie for nontrans BSS /* generate new ie for nontrans BSS
* 1. replace SSID with nontrans BSS' SSID * 1. replace SSID with nontrans BSS' SSID
* 2. skip MBSSID IE * 2. skip MBSSID IE
*/ */
new_ie = kzalloc(new_ie_len, gfp); new_ie = kzalloc(new_ie_len, GFP_ATOMIC);
if (!new_ie) if (!new_ie)
return; return;
new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, gfp);
new_ies = kzalloc(sizeof(*new_ies) + new_ie_len, GFP_ATOMIC);
if (!new_ies) if (!new_ies)
goto out_free; goto out_free;
@ -1901,6 +1901,8 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
cfg80211_parse_mbssid_frame_data(wiphy, data, mgmt, len, cfg80211_parse_mbssid_frame_data(wiphy, data, mgmt, len,
&non_tx_data, gfp); &non_tx_data, gfp);
spin_lock_bh(&wiphy_to_rdev(wiphy)->bss_lock);
/* check if the res has other nontransmitting bss which is not /* check if the res has other nontransmitting bss which is not
* in MBSSID IE * in MBSSID IE
*/ */
@ -1915,8 +1917,9 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
ies2 = rcu_access_pointer(tmp_bss->ies); ies2 = rcu_access_pointer(tmp_bss->ies);
if (ies2->tsf < ies1->tsf) if (ies2->tsf < ies1->tsf)
cfg80211_update_notlisted_nontrans(wiphy, tmp_bss, cfg80211_update_notlisted_nontrans(wiphy, tmp_bss,
mgmt, len, gfp); mgmt, len);
} }
spin_unlock_bh(&wiphy_to_rdev(wiphy)->bss_lock);
return res; return res;
} }

View File

@ -202,6 +202,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
struct iw_point *data, char *ssid) struct iw_point *data, char *ssid)
{ {
struct wireless_dev *wdev = dev->ieee80211_ptr; struct wireless_dev *wdev = dev->ieee80211_ptr;
int ret = 0;
/* call only for station! */ /* call only for station! */
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION)) if (WARN_ON(wdev->iftype != NL80211_IFTYPE_STATION))
@ -219,7 +220,10 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
if (ie) { if (ie) {
data->flags = 1; data->flags = 1;
data->length = ie[1]; data->length = ie[1];
memcpy(ssid, ie + 2, data->length); if (data->length > IW_ESSID_MAX_SIZE)
ret = -EINVAL;
else
memcpy(ssid, ie + 2, data->length);
} }
rcu_read_unlock(); rcu_read_unlock();
} else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) { } else if (wdev->wext.connect.ssid && wdev->wext.connect.ssid_len) {
@ -229,7 +233,7 @@ int cfg80211_mgd_wext_giwessid(struct net_device *dev,
} }
wdev_unlock(wdev); wdev_unlock(wdev);
return 0; return ret;
} }
int cfg80211_mgd_wext_siwap(struct net_device *dev, int cfg80211_mgd_wext_siwap(struct net_device *dev,