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:
commit
a17fd2cf2d
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
*
|
*
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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))
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
Loading…
Reference in New Issue