mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-02 16:44:10 +08:00
A fairly large number of fixes this time:
* fix a station info memory leak on insert collisions * a rate control fix for retransmissions * two aggregation setup fixes * reload current regdomain when reloading database * a locking fix in regulatory work * a probe request allocation size fix in mac80211 * apply TCP vs. aggregation (sk pacing) on mesh * fix ordering of channel context update vs. station state * set up skb->dev for mesh forwarding properly * track QoS data frames only for admission control to avoid out-of-bounds read (found by syzbot) * validate extended element ID vs. existing data to avoid out-of-bounds read (found by syzbot) * fix locking in mac80211 aggregation TX setup * fix traffic stall after HW restart when TXQs are used * fix ordering of reconfig/restart after HW restart * fix interface type for extended aggregation capability lookup -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEH1e1rEeCd0AIMq6MB8qZga/fl8QFAmG4dWoACgkQB8qZga/f l8Sorw//TtgV3lufyv4i0aYKzARw/V7vhDkt+FdPNbTKb9p4jkKkfwMyQttmqJrt 6yjjFZEiY7Z2ZzZ16k+EkNFmpV41DCmJTqRLg/1D+FsDlIIOWBsOifqUdnudLWXR WboegggjMZHaty6ebpA93exh5K6c058JY5YJRpP+I/0RDtOSEiv5gI1akxnRQsz4 /r9RsHy9+2zzyQC37/QBfljHPXAtF7UYRENUqPbc7wMFtX1I0/iWEVIXiHu5NC+g bVjZSEooChjpfHamle9paamfWIqE6yNFcwlTBH2vyuAupPAFJEIioCwLQjU4ACzx 8MZFlV8LZNRF1MP3owdOBPG+puPSRGgLa/3vvDybRTKWxJ2VZFoCXiEDVF7W8mJj GGCFkp268unSnLvRBXFRy3tw2vAaMcfeHx6aAUNKF8FQGGy9efoQfNVPNConbhld NlPkMa0I/kxLOBX8uJHtLekNb49EsWAs7NUGnUucXlxEAvp3jdcqguksbYmVukQT WHwlnIV929chOrT6zO3mSzCZW7ZeS7qAmVINzkKHP/7XGIzBbsRq5K4nie9Inoc+ EV9E+F+a1Drm8VksKvVGqbqmvhh+uZrBEKo+4Auaz0+/PZyo6uBQZHn2G3tGl42f iNUDEaNtkVqFA8q8bl6jEdj2lM1YtLtaP9kDKkg6IH4ZWv8g+Ps= =4LtY -----END PGP SIGNATURE----- Merge tag 'mac80211-for-net-2021-12-14' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211 Johannes Berg says: ==================== A fairly large number of fixes this time: * fix a station info memory leak on insert collisions * a rate control fix for retransmissions * two aggregation setup fixes * reload current regdomain when reloading database * a locking fix in regulatory work * a probe request allocation size fix in mac80211 * apply TCP vs. aggregation (sk pacing) on mesh * fix ordering of channel context update vs. station state * set up skb->dev for mesh forwarding properly * track QoS data frames only for admission control to avoid out-of-bounds read (found by syzbot) * validate extended element ID vs. existing data to avoid out-of-bounds read (found by syzbot) * fix locking in mac80211 aggregation TX setup * fix traffic stall after HW restart when TXQs are used * fix ordering of reconfig/restart after HW restart * fix interface type for extended aggregation capability lookup ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
d971650e17
@ -9,7 +9,7 @@
|
||||
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
||||
* Copyright 2007-2010, Intel Corporation
|
||||
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
* Copyright (C) 2018-2021 Intel Corporation
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -191,7 +191,8 @@ static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata,
|
||||
sband = ieee80211_get_sband(sdata);
|
||||
if (!sband)
|
||||
return;
|
||||
he_cap = ieee80211_get_he_iftype_cap(sband, sdata->vif.type);
|
||||
he_cap = ieee80211_get_he_iftype_cap(sband,
|
||||
ieee80211_vif_type_p2p(&sdata->vif));
|
||||
if (!he_cap)
|
||||
return;
|
||||
|
||||
|
@ -9,7 +9,7 @@
|
||||
* Copyright 2007, Michael Wu <flamingice@sourmilk.net>
|
||||
* Copyright 2007-2010, Intel Corporation
|
||||
* Copyright(c) 2015-2017 Intel Deutschland GmbH
|
||||
* Copyright (C) 2018 - 2020 Intel Corporation
|
||||
* Copyright (C) 2018 - 2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/ieee80211.h>
|
||||
@ -106,7 +106,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
|
||||
mgmt->u.action.u.addba_req.start_seq_num =
|
||||
cpu_to_le16(start_seq_num << 4);
|
||||
|
||||
ieee80211_tx_skb(sdata, skb);
|
||||
ieee80211_tx_skb_tid(sdata, skb, tid);
|
||||
}
|
||||
|
||||
void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn)
|
||||
@ -213,6 +213,8 @@ ieee80211_agg_start_txq(struct sta_info *sta, int tid, bool enable)
|
||||
struct ieee80211_txq *txq = sta->sta.txq[tid];
|
||||
struct txq_info *txqi;
|
||||
|
||||
lockdep_assert_held(&sta->ampdu_mlme.mtx);
|
||||
|
||||
if (!txq)
|
||||
return;
|
||||
|
||||
@ -290,7 +292,6 @@ static void ieee80211_remove_tid_tx(struct sta_info *sta, int tid)
|
||||
ieee80211_assign_tid_tx(sta, tid, NULL);
|
||||
|
||||
ieee80211_agg_splice_finish(sta->sdata, tid);
|
||||
ieee80211_agg_start_txq(sta, tid, false);
|
||||
|
||||
kfree_rcu(tid_tx, rcu_head);
|
||||
}
|
||||
@ -480,8 +481,7 @@ static void ieee80211_send_addba_with_timeout(struct sta_info *sta,
|
||||
|
||||
/* send AddBA request */
|
||||
ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
|
||||
tid_tx->dialog_token,
|
||||
sta->tid_seq[tid] >> 4,
|
||||
tid_tx->dialog_token, tid_tx->ssn,
|
||||
buf_size, tid_tx->timeout);
|
||||
|
||||
WARN_ON(test_and_set_bit(HT_AGG_STATE_SENT_ADDBA, &tid_tx->state));
|
||||
@ -523,6 +523,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
|
||||
|
||||
params.ssn = sta->tid_seq[tid] >> 4;
|
||||
ret = drv_ampdu_action(local, sdata, ¶ms);
|
||||
tid_tx->ssn = params.ssn;
|
||||
if (ret == IEEE80211_AMPDU_TX_START_DELAY_ADDBA) {
|
||||
return;
|
||||
} else if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) {
|
||||
@ -889,6 +890,7 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
bool send_delba = false;
|
||||
bool start_txq = false;
|
||||
|
||||
ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n",
|
||||
sta->sta.addr, tid);
|
||||
@ -906,10 +908,14 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
|
||||
send_delba = true;
|
||||
|
||||
ieee80211_remove_tid_tx(sta, tid);
|
||||
start_txq = true;
|
||||
|
||||
unlock_sta:
|
||||
spin_unlock_bh(&sta->lock);
|
||||
|
||||
if (start_txq)
|
||||
ieee80211_agg_start_txq(sta, tid, false);
|
||||
|
||||
if (send_delba)
|
||||
ieee80211_send_delba(sdata, sta->sta.addr, tid,
|
||||
WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
|
||||
|
@ -1219,8 +1219,11 @@ static inline void drv_wake_tx_queue(struct ieee80211_local *local,
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif);
|
||||
|
||||
if (local->in_reconfig)
|
||||
/* In reconfig don't transmit now, but mark for waking later */
|
||||
if (local->in_reconfig) {
|
||||
set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txq->flags);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!check_sdata_in_driver(sdata))
|
||||
return;
|
||||
|
@ -2452,11 +2452,18 @@ static void ieee80211_sta_tx_wmm_ac_notify(struct ieee80211_sub_if_data *sdata,
|
||||
u16 tx_time)
|
||||
{
|
||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||
u16 tid = ieee80211_get_tid(hdr);
|
||||
int ac = ieee80211_ac_from_tid(tid);
|
||||
struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
|
||||
u16 tid;
|
||||
int ac;
|
||||
struct ieee80211_sta_tx_tspec *tx_tspec;
|
||||
unsigned long now = jiffies;
|
||||
|
||||
if (!ieee80211_is_data_qos(hdr->frame_control))
|
||||
return;
|
||||
|
||||
tid = ieee80211_get_tid(hdr);
|
||||
ac = ieee80211_ac_from_tid(tid);
|
||||
tx_tspec = &ifmgd->tx_tspec[ac];
|
||||
|
||||
if (likely(!tx_tspec->admitted_time))
|
||||
return;
|
||||
|
||||
|
@ -2944,6 +2944,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
|
||||
if (!fwd_skb)
|
||||
goto out;
|
||||
|
||||
fwd_skb->dev = sdata->dev;
|
||||
fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
|
||||
fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);
|
||||
info = IEEE80211_SKB_CB(fwd_skb);
|
||||
|
@ -644,13 +644,13 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
|
||||
/* check if STA exists already */
|
||||
if (sta_info_get_bss(sdata, sta->sta.addr)) {
|
||||
err = -EEXIST;
|
||||
goto out_err;
|
||||
goto out_cleanup;
|
||||
}
|
||||
|
||||
sinfo = kzalloc(sizeof(struct station_info), GFP_KERNEL);
|
||||
if (!sinfo) {
|
||||
err = -ENOMEM;
|
||||
goto out_err;
|
||||
goto out_cleanup;
|
||||
}
|
||||
|
||||
local->num_sta++;
|
||||
@ -667,6 +667,15 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
|
||||
|
||||
list_add_tail_rcu(&sta->list, &local->sta_list);
|
||||
|
||||
/* update channel context before notifying the driver about state
|
||||
* change, this enables driver using the updated channel context right away.
|
||||
*/
|
||||
if (sta->sta_state >= IEEE80211_STA_ASSOC) {
|
||||
ieee80211_recalc_min_chandef(sta->sdata);
|
||||
if (!sta->sta.support_p2p_ps)
|
||||
ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
|
||||
}
|
||||
|
||||
/* notify driver */
|
||||
err = sta_info_insert_drv_state(local, sdata, sta);
|
||||
if (err)
|
||||
@ -674,12 +683,6 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
|
||||
|
||||
set_sta_flag(sta, WLAN_STA_INSERTED);
|
||||
|
||||
if (sta->sta_state >= IEEE80211_STA_ASSOC) {
|
||||
ieee80211_recalc_min_chandef(sta->sdata);
|
||||
if (!sta->sta.support_p2p_ps)
|
||||
ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
|
||||
}
|
||||
|
||||
/* accept BA sessions now */
|
||||
clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
|
||||
|
||||
@ -706,8 +709,8 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
|
||||
out_drop_sta:
|
||||
local->num_sta--;
|
||||
synchronize_net();
|
||||
out_cleanup:
|
||||
cleanup_single_sta(sta);
|
||||
out_err:
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
kfree(sinfo);
|
||||
rcu_read_lock();
|
||||
|
@ -176,6 +176,7 @@ struct sta_info;
|
||||
* @failed_bar_ssn: ssn of the last failed BAR tx attempt
|
||||
* @bar_pending: BAR needs to be re-sent
|
||||
* @amsdu: support A-MSDU withing A-MDPU
|
||||
* @ssn: starting sequence number of the session
|
||||
*
|
||||
* This structure's lifetime is managed by RCU, assignments to
|
||||
* the array holding it must hold the aggregation mutex.
|
||||
@ -199,6 +200,7 @@ struct tid_ampdu_tx {
|
||||
u8 stop_initiator;
|
||||
bool tx_stop;
|
||||
u16 buf_size;
|
||||
u16 ssn;
|
||||
|
||||
u16 failed_bar_ssn;
|
||||
bool bar_pending;
|
||||
|
@ -1822,15 +1822,15 @@ static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx)
|
||||
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
|
||||
ieee80211_tx_result res = TX_CONTINUE;
|
||||
|
||||
if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
|
||||
CALL_TXH(ieee80211_tx_h_rate_ctrl);
|
||||
|
||||
if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) {
|
||||
__skb_queue_tail(&tx->skbs, tx->skb);
|
||||
tx->skb = NULL;
|
||||
goto txh_done;
|
||||
}
|
||||
|
||||
if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
|
||||
CALL_TXH(ieee80211_tx_h_rate_ctrl);
|
||||
|
||||
CALL_TXH(ieee80211_tx_h_michael_mic_add);
|
||||
CALL_TXH(ieee80211_tx_h_sequence);
|
||||
CALL_TXH(ieee80211_tx_h_fragment);
|
||||
@ -4191,11 +4191,11 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
|
||||
|
||||
ieee80211_aggr_check(sdata, sta, skb);
|
||||
|
||||
sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
|
||||
|
||||
if (sta) {
|
||||
struct ieee80211_fast_tx *fast_tx;
|
||||
|
||||
sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
|
||||
|
||||
fast_tx = rcu_dereference(sta->fast_tx);
|
||||
|
||||
if (fast_tx &&
|
||||
|
@ -943,7 +943,12 @@ static void ieee80211_parse_extension_element(u32 *crc,
|
||||
struct ieee802_11_elems *elems)
|
||||
{
|
||||
const void *data = elem->data + 1;
|
||||
u8 len = elem->datalen - 1;
|
||||
u8 len;
|
||||
|
||||
if (!elem->datalen)
|
||||
return;
|
||||
|
||||
len = elem->datalen - 1;
|
||||
|
||||
switch (elem->data[0]) {
|
||||
case WLAN_EID_EXT_HE_MU_EDCA:
|
||||
@ -2063,7 +2068,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
|
||||
chandef.chan = chan;
|
||||
|
||||
skb = ieee80211_probereq_get(&local->hw, src, ssid, ssid_len,
|
||||
100 + ie_len);
|
||||
local->scan_ies_len + ie_len);
|
||||
if (!skb)
|
||||
return NULL;
|
||||
|
||||
@ -2646,6 +2651,13 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
mutex_unlock(&local->sta_mtx);
|
||||
}
|
||||
|
||||
/*
|
||||
* If this is for hw restart things are still running.
|
||||
* We may want to change that later, however.
|
||||
*/
|
||||
if (local->open_count && (!suspended || reconfig_due_to_wowlan))
|
||||
drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART);
|
||||
|
||||
if (local->in_reconfig) {
|
||||
local->in_reconfig = false;
|
||||
barrier();
|
||||
@ -2664,13 +2676,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND,
|
||||
false);
|
||||
|
||||
/*
|
||||
* If this is for hw restart things are still running.
|
||||
* We may want to change that later, however.
|
||||
*/
|
||||
if (local->open_count && (!suspended || reconfig_due_to_wowlan))
|
||||
drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART);
|
||||
|
||||
if (!suspended)
|
||||
return 0;
|
||||
|
||||
|
@ -133,6 +133,7 @@ static u32 reg_is_indoor_portid;
|
||||
|
||||
static void restore_regulatory_settings(bool reset_user, bool cached);
|
||||
static void print_regdomain(const struct ieee80211_regdomain *rd);
|
||||
static void reg_process_hint(struct regulatory_request *reg_request);
|
||||
|
||||
static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
|
||||
{
|
||||
@ -1098,6 +1099,8 @@ int reg_reload_regdb(void)
|
||||
const struct firmware *fw;
|
||||
void *db;
|
||||
int err;
|
||||
const struct ieee80211_regdomain *current_regdomain;
|
||||
struct regulatory_request *request;
|
||||
|
||||
err = request_firmware(&fw, "regulatory.db", ®_pdev->dev);
|
||||
if (err)
|
||||
@ -1118,8 +1121,26 @@ int reg_reload_regdb(void)
|
||||
if (!IS_ERR_OR_NULL(regdb))
|
||||
kfree(regdb);
|
||||
regdb = db;
|
||||
rtnl_unlock();
|
||||
|
||||
/* reset regulatory domain */
|
||||
current_regdomain = get_cfg80211_regdom();
|
||||
|
||||
request = kzalloc(sizeof(*request), GFP_KERNEL);
|
||||
if (!request) {
|
||||
err = -ENOMEM;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
request->wiphy_idx = WIPHY_IDX_INVALID;
|
||||
request->alpha2[0] = current_regdomain->alpha2[0];
|
||||
request->alpha2[1] = current_regdomain->alpha2[1];
|
||||
request->initiator = NL80211_REGDOM_SET_BY_CORE;
|
||||
request->user_reg_hint_type = NL80211_USER_REG_HINT_USER;
|
||||
|
||||
reg_process_hint(request);
|
||||
|
||||
out_unlock:
|
||||
rtnl_unlock();
|
||||
out:
|
||||
release_firmware(fw);
|
||||
return err;
|
||||
@ -2338,6 +2359,7 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
struct cfg80211_chan_def chandef = {};
|
||||
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
|
||||
enum nl80211_iftype iftype;
|
||||
bool ret;
|
||||
|
||||
wdev_lock(wdev);
|
||||
iftype = wdev->iftype;
|
||||
@ -2387,7 +2409,11 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
|
||||
case NL80211_IFTYPE_AP:
|
||||
case NL80211_IFTYPE_P2P_GO:
|
||||
case NL80211_IFTYPE_ADHOC:
|
||||
return cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype);
|
||||
wiphy_lock(wiphy);
|
||||
ret = cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype);
|
||||
wiphy_unlock(wiphy);
|
||||
|
||||
return ret;
|
||||
case NL80211_IFTYPE_STATION:
|
||||
case NL80211_IFTYPE_P2P_CLIENT:
|
||||
return cfg80211_chandef_usable(wiphy, &chandef,
|
||||
|
Loading…
Reference in New Issue
Block a user