Merge tag 'mac80211-for-davem-2019-06-14' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211
Johannes Berg says: ==================== Various fixes, all over: * a few memory leaks * fixes for management frame protection security and A2/A3 confusion (affecting TDLS as well) * build fix for certificates * etc. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -1435,7 +1435,7 @@ ieee80211_get_sband(struct ieee80211_sub_if_data *sdata)
|
||||
rcu_read_lock();
|
||||
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
|
||||
|
||||
if (WARN_ON(!chanctx_conf)) {
|
||||
if (WARN_ON_ONCE(!chanctx_conf)) {
|
||||
rcu_read_unlock();
|
||||
return NULL;
|
||||
}
|
||||
@@ -2037,6 +2037,13 @@ void __ieee80211_flush_queues(struct ieee80211_local *local,
|
||||
|
||||
static inline bool ieee80211_can_run_worker(struct ieee80211_local *local)
|
||||
{
|
||||
/*
|
||||
* It's unsafe to try to do any work during reconfigure flow.
|
||||
* When the flow ends the work will be requeued.
|
||||
*/
|
||||
if (local->in_reconfig)
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If quiescing is set, we are racing with __ieee80211_suspend.
|
||||
* __ieee80211_suspend flushes the workers after setting quiescing,
|
||||
@@ -2225,6 +2232,9 @@ void ieee80211_tdls_cancel_channel_switch(struct wiphy *wiphy,
|
||||
const u8 *addr);
|
||||
void ieee80211_teardown_tdls_peers(struct ieee80211_sub_if_data *sdata);
|
||||
void ieee80211_tdls_chsw_work(struct work_struct *wk);
|
||||
void ieee80211_tdls_handle_disconnect(struct ieee80211_sub_if_data *sdata,
|
||||
const u8 *peer, u16 reason);
|
||||
const char *ieee80211_get_reason_code_string(u16 reason_code);
|
||||
|
||||
extern const struct ethtool_ops ieee80211_ethtool_ops;
|
||||
|
||||
|
@@ -268,11 +268,9 @@ int ieee80211_set_tx_key(struct ieee80211_key *key)
|
||||
{
|
||||
struct sta_info *sta = key->sta;
|
||||
struct ieee80211_local *local = key->local;
|
||||
struct ieee80211_key *old;
|
||||
|
||||
assert_key_lock(local);
|
||||
|
||||
old = key_mtx_dereference(local, sta->ptk[sta->ptk_idx]);
|
||||
sta->ptk_idx = key->conf.keyidx;
|
||||
ieee80211_check_fast_xmit(sta);
|
||||
|
||||
|
@@ -929,6 +929,7 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
|
||||
|
||||
/* flush STAs and mpaths on this iface */
|
||||
sta_info_flush(sdata);
|
||||
ieee80211_free_keys(sdata, true);
|
||||
mesh_path_flush_by_iface(sdata);
|
||||
|
||||
/* stop the beacon */
|
||||
@@ -1220,7 +1221,8 @@ int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
|
||||
ifmsh->chsw_ttl = 0;
|
||||
|
||||
/* Remove the CSA and MCSP elements from the beacon */
|
||||
tmp_csa_settings = rcu_dereference(ifmsh->csa);
|
||||
tmp_csa_settings = rcu_dereference_protected(ifmsh->csa,
|
||||
lockdep_is_held(&sdata->wdev.mtx));
|
||||
RCU_INIT_POINTER(ifmsh->csa, NULL);
|
||||
if (tmp_csa_settings)
|
||||
kfree_rcu(tmp_csa_settings, rcu_head);
|
||||
@@ -1242,6 +1244,8 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
|
||||
struct mesh_csa_settings *tmp_csa_settings;
|
||||
int ret = 0;
|
||||
|
||||
lockdep_assert_held(&sdata->wdev.mtx);
|
||||
|
||||
tmp_csa_settings = kmalloc(sizeof(*tmp_csa_settings),
|
||||
GFP_ATOMIC);
|
||||
if (!tmp_csa_settings)
|
||||
|
@@ -2963,7 +2963,7 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
|
||||
#define case_WLAN(type) \
|
||||
case WLAN_REASON_##type: return #type
|
||||
|
||||
static const char *ieee80211_get_reason_code_string(u16 reason_code)
|
||||
const char *ieee80211_get_reason_code_string(u16 reason_code)
|
||||
{
|
||||
switch (reason_code) {
|
||||
case_WLAN(UNSPECIFIED);
|
||||
@@ -3028,6 +3028,11 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
|
||||
if (len < 24 + 2)
|
||||
return;
|
||||
|
||||
if (!ether_addr_equal(mgmt->bssid, mgmt->sa)) {
|
||||
ieee80211_tdls_handle_disconnect(sdata, mgmt->sa, reason_code);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ifmgd->associated &&
|
||||
ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) {
|
||||
const u8 *bssid = ifmgd->associated->bssid;
|
||||
@@ -3077,6 +3082,11 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
|
||||
|
||||
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
|
||||
|
||||
if (!ether_addr_equal(mgmt->bssid, mgmt->sa)) {
|
||||
ieee80211_tdls_handle_disconnect(sdata, mgmt->sa, reason_code);
|
||||
return;
|
||||
}
|
||||
|
||||
sdata_info(sdata, "disassociated from %pM (Reason: %u=%s)\n",
|
||||
mgmt->sa, reason_code,
|
||||
ieee80211_get_reason_code_string(reason_code));
|
||||
|
@@ -3831,6 +3831,8 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
|
||||
case NL80211_IFTYPE_STATION:
|
||||
if (!bssid && !sdata->u.mgd.use_4addr)
|
||||
return false;
|
||||
if (ieee80211_is_robust_mgmt_frame(skb) && !rx->sta)
|
||||
return false;
|
||||
if (multicast)
|
||||
return true;
|
||||
return ether_addr_equal(sdata->vif.addr, hdr->addr1);
|
||||
|
@@ -1994,3 +1994,26 @@ void ieee80211_tdls_chsw_work(struct work_struct *wk)
|
||||
}
|
||||
rtnl_unlock();
|
||||
}
|
||||
|
||||
void ieee80211_tdls_handle_disconnect(struct ieee80211_sub_if_data *sdata,
|
||||
const u8 *peer, u16 reason)
|
||||
{
|
||||
struct ieee80211_sta *sta;
|
||||
|
||||
rcu_read_lock();
|
||||
sta = ieee80211_find_sta(&sdata->vif, peer);
|
||||
if (!sta || !sta->tdls) {
|
||||
rcu_read_unlock();
|
||||
return;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
tdls_dbg(sdata, "disconnected from TDLS peer %pM (Reason: %u=%s)\n",
|
||||
peer, reason,
|
||||
ieee80211_get_reason_code_string(reason));
|
||||
|
||||
ieee80211_tdls_oper_request(&sdata->vif, peer,
|
||||
NL80211_TDLS_TEARDOWN,
|
||||
WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE,
|
||||
GFP_ATOMIC);
|
||||
}
|
||||
|
@@ -2480,6 +2480,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
mutex_lock(&local->mtx);
|
||||
ieee80211_start_next_roc(local);
|
||||
mutex_unlock(&local->mtx);
|
||||
|
||||
/* Requeue all works */
|
||||
list_for_each_entry(sdata, &local->interfaces, list)
|
||||
ieee80211_queue_work(&local->hw, &sdata->work);
|
||||
}
|
||||
|
||||
ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
|
||||
@@ -3795,7 +3799,9 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
|
||||
}
|
||||
|
||||
/* Always allow software iftypes */
|
||||
if (local->hw.wiphy->software_iftypes & BIT(iftype)) {
|
||||
if (local->hw.wiphy->software_iftypes & BIT(iftype) ||
|
||||
(iftype == NL80211_IFTYPE_AP_VLAN &&
|
||||
local->hw.wiphy->flags & WIPHY_FLAG_4ADDR_AP)) {
|
||||
if (radar_detect)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
|
@@ -1175,7 +1175,7 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
|
||||
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
|
||||
struct ieee80211_key *key = rx->key;
|
||||
struct ieee80211_mmie_16 *mmie;
|
||||
u8 aad[GMAC_AAD_LEN], mic[GMAC_MIC_LEN], ipn[6], nonce[GMAC_NONCE_LEN];
|
||||
u8 aad[GMAC_AAD_LEN], *mic, ipn[6], nonce[GMAC_NONCE_LEN];
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
if (!ieee80211_is_mgmt(hdr->frame_control))
|
||||
@@ -1206,13 +1206,18 @@ ieee80211_crypto_aes_gmac_decrypt(struct ieee80211_rx_data *rx)
|
||||
memcpy(nonce, hdr->addr2, ETH_ALEN);
|
||||
memcpy(nonce + ETH_ALEN, ipn, 6);
|
||||
|
||||
mic = kmalloc(GMAC_MIC_LEN, GFP_ATOMIC);
|
||||
if (!mic)
|
||||
return RX_DROP_UNUSABLE;
|
||||
if (ieee80211_aes_gmac(key->u.aes_gmac.tfm, aad, nonce,
|
||||
skb->data + 24, skb->len - 24,
|
||||
mic) < 0 ||
|
||||
crypto_memneq(mic, mmie->mic, sizeof(mmie->mic))) {
|
||||
key->u.aes_gmac.icverrors++;
|
||||
kfree(mic);
|
||||
return RX_DROP_UNUSABLE;
|
||||
}
|
||||
kfree(mic);
|
||||
}
|
||||
|
||||
memcpy(key->u.aes_gmac.rx_pn, ipn, 6);
|
||||
|
Reference in New Issue
Block a user