Skip to content

Commit d971650

Browse files
committed
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 <[email protected]>
2 parents a41c4d9 + 13dee10 commit d971650

File tree

10 files changed

+90
-36
lines changed

10 files changed

+90
-36
lines changed

net/mac80211/agg-rx.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Copyright 2007, Michael Wu <[email protected]>
1010
* Copyright 2007-2010, Intel Corporation
1111
* Copyright(c) 2015-2017 Intel Deutschland GmbH
12-
* Copyright (C) 2018-2020 Intel Corporation
12+
* Copyright (C) 2018-2021 Intel Corporation
1313
*/
1414

1515
/**
@@ -191,7 +191,8 @@ static void ieee80211_add_addbaext(struct ieee80211_sub_if_data *sdata,
191191
sband = ieee80211_get_sband(sdata);
192192
if (!sband)
193193
return;
194-
he_cap = ieee80211_get_he_iftype_cap(sband, sdata->vif.type);
194+
he_cap = ieee80211_get_he_iftype_cap(sband,
195+
ieee80211_vif_type_p2p(&sdata->vif));
195196
if (!he_cap)
196197
return;
197198

net/mac80211/agg-tx.c

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
* Copyright 2007, Michael Wu <[email protected]>
1010
* Copyright 2007-2010, Intel Corporation
1111
* Copyright(c) 2015-2017 Intel Deutschland GmbH
12-
* Copyright (C) 2018 - 2020 Intel Corporation
12+
* Copyright (C) 2018 - 2021 Intel Corporation
1313
*/
1414

1515
#include <linux/ieee80211.h>
@@ -106,7 +106,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata,
106106
mgmt->u.action.u.addba_req.start_seq_num =
107107
cpu_to_le16(start_seq_num << 4);
108108

109-
ieee80211_tx_skb(sdata, skb);
109+
ieee80211_tx_skb_tid(sdata, skb, tid);
110110
}
111111

112112
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)
213213
struct ieee80211_txq *txq = sta->sta.txq[tid];
214214
struct txq_info *txqi;
215215

216+
lockdep_assert_held(&sta->ampdu_mlme.mtx);
217+
216218
if (!txq)
217219
return;
218220

@@ -290,7 +292,6 @@ static void ieee80211_remove_tid_tx(struct sta_info *sta, int tid)
290292
ieee80211_assign_tid_tx(sta, tid, NULL);
291293

292294
ieee80211_agg_splice_finish(sta->sdata, tid);
293-
ieee80211_agg_start_txq(sta, tid, false);
294295

295296
kfree_rcu(tid_tx, rcu_head);
296297
}
@@ -480,8 +481,7 @@ static void ieee80211_send_addba_with_timeout(struct sta_info *sta,
480481

481482
/* send AddBA request */
482483
ieee80211_send_addba_request(sdata, sta->sta.addr, tid,
483-
tid_tx->dialog_token,
484-
sta->tid_seq[tid] >> 4,
484+
tid_tx->dialog_token, tid_tx->ssn,
485485
buf_size, tid_tx->timeout);
486486

487487
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)
523523

524524
params.ssn = sta->tid_seq[tid] >> 4;
525525
ret = drv_ampdu_action(local, sdata, &params);
526+
tid_tx->ssn = params.ssn;
526527
if (ret == IEEE80211_AMPDU_TX_START_DELAY_ADDBA) {
527528
return;
528529
} else if (ret == IEEE80211_AMPDU_TX_START_IMMEDIATE) {
@@ -889,6 +890,7 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
889890
{
890891
struct ieee80211_sub_if_data *sdata = sta->sdata;
891892
bool send_delba = false;
893+
bool start_txq = false;
892894

893895
ht_dbg(sdata, "Stopping Tx BA session for %pM tid %d\n",
894896
sta->sta.addr, tid);
@@ -906,10 +908,14 @@ void ieee80211_stop_tx_ba_cb(struct sta_info *sta, int tid,
906908
send_delba = true;
907909

908910
ieee80211_remove_tid_tx(sta, tid);
911+
start_txq = true;
909912

910913
unlock_sta:
911914
spin_unlock_bh(&sta->lock);
912915

916+
if (start_txq)
917+
ieee80211_agg_start_txq(sta, tid, false);
918+
913919
if (send_delba)
914920
ieee80211_send_delba(sdata, sta->sta.addr, tid,
915921
WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);

net/mac80211/driver-ops.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1219,8 +1219,11 @@ static inline void drv_wake_tx_queue(struct ieee80211_local *local,
12191219
{
12201220
struct ieee80211_sub_if_data *sdata = vif_to_sdata(txq->txq.vif);
12211221

1222-
if (local->in_reconfig)
1222+
/* In reconfig don't transmit now, but mark for waking later */
1223+
if (local->in_reconfig) {
1224+
set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txq->flags);
12231225
return;
1226+
}
12241227

12251228
if (!check_sdata_in_driver(sdata))
12261229
return;

net/mac80211/mlme.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2452,11 +2452,18 @@ static void ieee80211_sta_tx_wmm_ac_notify(struct ieee80211_sub_if_data *sdata,
24522452
u16 tx_time)
24532453
{
24542454
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2455-
u16 tid = ieee80211_get_tid(hdr);
2456-
int ac = ieee80211_ac_from_tid(tid);
2457-
struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
2455+
u16 tid;
2456+
int ac;
2457+
struct ieee80211_sta_tx_tspec *tx_tspec;
24582458
unsigned long now = jiffies;
24592459

2460+
if (!ieee80211_is_data_qos(hdr->frame_control))
2461+
return;
2462+
2463+
tid = ieee80211_get_tid(hdr);
2464+
ac = ieee80211_ac_from_tid(tid);
2465+
tx_tspec = &ifmgd->tx_tspec[ac];
2466+
24602467
if (likely(!tx_tspec->admitted_time))
24612468
return;
24622469

net/mac80211/rx.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2944,6 +2944,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
29442944
if (!fwd_skb)
29452945
goto out;
29462946

2947+
fwd_skb->dev = sdata->dev;
29472948
fwd_hdr = (struct ieee80211_hdr *) fwd_skb->data;
29482949
fwd_hdr->frame_control &= ~cpu_to_le16(IEEE80211_FCTL_RETRY);
29492950
info = IEEE80211_SKB_CB(fwd_skb);

net/mac80211/sta_info.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -644,13 +644,13 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
644644
/* check if STA exists already */
645645
if (sta_info_get_bss(sdata, sta->sta.addr)) {
646646
err = -EEXIST;
647-
goto out_err;
647+
goto out_cleanup;
648648
}
649649

650650
sinfo = kzalloc(sizeof(struct station_info), GFP_KERNEL);
651651
if (!sinfo) {
652652
err = -ENOMEM;
653-
goto out_err;
653+
goto out_cleanup;
654654
}
655655

656656
local->num_sta++;
@@ -667,19 +667,22 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
667667

668668
list_add_tail_rcu(&sta->list, &local->sta_list);
669669

670+
/* update channel context before notifying the driver about state
671+
* change, this enables driver using the updated channel context right away.
672+
*/
673+
if (sta->sta_state >= IEEE80211_STA_ASSOC) {
674+
ieee80211_recalc_min_chandef(sta->sdata);
675+
if (!sta->sta.support_p2p_ps)
676+
ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
677+
}
678+
670679
/* notify driver */
671680
err = sta_info_insert_drv_state(local, sdata, sta);
672681
if (err)
673682
goto out_remove;
674683

675684
set_sta_flag(sta, WLAN_STA_INSERTED);
676685

677-
if (sta->sta_state >= IEEE80211_STA_ASSOC) {
678-
ieee80211_recalc_min_chandef(sta->sdata);
679-
if (!sta->sta.support_p2p_ps)
680-
ieee80211_recalc_p2p_go_ps_allowed(sta->sdata);
681-
}
682-
683686
/* accept BA sessions now */
684687
clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
685688

@@ -706,8 +709,8 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)
706709
out_drop_sta:
707710
local->num_sta--;
708711
synchronize_net();
712+
out_cleanup:
709713
cleanup_single_sta(sta);
710-
out_err:
711714
mutex_unlock(&local->sta_mtx);
712715
kfree(sinfo);
713716
rcu_read_lock();

net/mac80211/sta_info.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ struct sta_info;
176176
* @failed_bar_ssn: ssn of the last failed BAR tx attempt
177177
* @bar_pending: BAR needs to be re-sent
178178
* @amsdu: support A-MSDU withing A-MDPU
179+
* @ssn: starting sequence number of the session
179180
*
180181
* This structure's lifetime is managed by RCU, assignments to
181182
* the array holding it must hold the aggregation mutex.
@@ -199,6 +200,7 @@ struct tid_ampdu_tx {
199200
u8 stop_initiator;
200201
bool tx_stop;
201202
u16 buf_size;
203+
u16 ssn;
202204

203205
u16 failed_bar_ssn;
204206
bool bar_pending;

net/mac80211/tx.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1822,15 +1822,15 @@ static int invoke_tx_handlers_late(struct ieee80211_tx_data *tx)
18221822
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
18231823
ieee80211_tx_result res = TX_CONTINUE;
18241824

1825+
if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
1826+
CALL_TXH(ieee80211_tx_h_rate_ctrl);
1827+
18251828
if (unlikely(info->flags & IEEE80211_TX_INTFL_RETRANSMISSION)) {
18261829
__skb_queue_tail(&tx->skbs, tx->skb);
18271830
tx->skb = NULL;
18281831
goto txh_done;
18291832
}
18301833

1831-
if (!ieee80211_hw_check(&tx->local->hw, HAS_RATE_CONTROL))
1832-
CALL_TXH(ieee80211_tx_h_rate_ctrl);
1833-
18341834
CALL_TXH(ieee80211_tx_h_michael_mic_add);
18351835
CALL_TXH(ieee80211_tx_h_sequence);
18361836
CALL_TXH(ieee80211_tx_h_fragment);
@@ -4191,11 +4191,11 @@ void __ieee80211_subif_start_xmit(struct sk_buff *skb,
41914191

41924192
ieee80211_aggr_check(sdata, sta, skb);
41934193

4194+
sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
4195+
41944196
if (sta) {
41954197
struct ieee80211_fast_tx *fast_tx;
41964198

4197-
sk_pacing_shift_update(skb->sk, sdata->local->hw.tx_sk_pacing_shift);
4198-
41994199
fast_tx = rcu_dereference(sta->fast_tx);
42004200

42014201
if (fast_tx &&

net/mac80211/util.c

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -943,7 +943,12 @@ static void ieee80211_parse_extension_element(u32 *crc,
943943
struct ieee802_11_elems *elems)
944944
{
945945
const void *data = elem->data + 1;
946-
u8 len = elem->datalen - 1;
946+
u8 len;
947+
948+
if (!elem->datalen)
949+
return;
950+
951+
len = elem->datalen - 1;
947952

948953
switch (elem->data[0]) {
949954
case WLAN_EID_EXT_HE_MU_EDCA:
@@ -2063,7 +2068,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
20632068
chandef.chan = chan;
20642069

20652070
skb = ieee80211_probereq_get(&local->hw, src, ssid, ssid_len,
2066-
100 + ie_len);
2071+
local->scan_ies_len + ie_len);
20672072
if (!skb)
20682073
return NULL;
20692074

@@ -2646,6 +2651,13 @@ int ieee80211_reconfig(struct ieee80211_local *local)
26462651
mutex_unlock(&local->sta_mtx);
26472652
}
26482653

2654+
/*
2655+
* If this is for hw restart things are still running.
2656+
* We may want to change that later, however.
2657+
*/
2658+
if (local->open_count && (!suspended || reconfig_due_to_wowlan))
2659+
drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART);
2660+
26492661
if (local->in_reconfig) {
26502662
local->in_reconfig = false;
26512663
barrier();
@@ -2664,13 +2676,6 @@ int ieee80211_reconfig(struct ieee80211_local *local)
26642676
IEEE80211_QUEUE_STOP_REASON_SUSPEND,
26652677
false);
26662678

2667-
/*
2668-
* If this is for hw restart things are still running.
2669-
* We may want to change that later, however.
2670-
*/
2671-
if (local->open_count && (!suspended || reconfig_due_to_wowlan))
2672-
drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART);
2673-
26742679
if (!suspended)
26752680
return 0;
26762681

net/wireless/reg.c

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ static u32 reg_is_indoor_portid;
133133

134134
static void restore_regulatory_settings(bool reset_user, bool cached);
135135
static void print_regdomain(const struct ieee80211_regdomain *rd);
136+
static void reg_process_hint(struct regulatory_request *reg_request);
136137

137138
static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
138139
{
@@ -1098,6 +1099,8 @@ int reg_reload_regdb(void)
10981099
const struct firmware *fw;
10991100
void *db;
11001101
int err;
1102+
const struct ieee80211_regdomain *current_regdomain;
1103+
struct regulatory_request *request;
11011104

11021105
err = request_firmware(&fw, "regulatory.db", &reg_pdev->dev);
11031106
if (err)
@@ -1118,8 +1121,26 @@ int reg_reload_regdb(void)
11181121
if (!IS_ERR_OR_NULL(regdb))
11191122
kfree(regdb);
11201123
regdb = db;
1121-
rtnl_unlock();
11221124

1125+
/* reset regulatory domain */
1126+
current_regdomain = get_cfg80211_regdom();
1127+
1128+
request = kzalloc(sizeof(*request), GFP_KERNEL);
1129+
if (!request) {
1130+
err = -ENOMEM;
1131+
goto out_unlock;
1132+
}
1133+
1134+
request->wiphy_idx = WIPHY_IDX_INVALID;
1135+
request->alpha2[0] = current_regdomain->alpha2[0];
1136+
request->alpha2[1] = current_regdomain->alpha2[1];
1137+
request->initiator = NL80211_REGDOM_SET_BY_CORE;
1138+
request->user_reg_hint_type = NL80211_USER_REG_HINT_USER;
1139+
1140+
reg_process_hint(request);
1141+
1142+
out_unlock:
1143+
rtnl_unlock();
11231144
out:
11241145
release_firmware(fw);
11251146
return err;
@@ -2338,6 +2359,7 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
23382359
struct cfg80211_chan_def chandef = {};
23392360
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
23402361
enum nl80211_iftype iftype;
2362+
bool ret;
23412363

23422364
wdev_lock(wdev);
23432365
iftype = wdev->iftype;
@@ -2387,7 +2409,11 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
23872409
case NL80211_IFTYPE_AP:
23882410
case NL80211_IFTYPE_P2P_GO:
23892411
case NL80211_IFTYPE_ADHOC:
2390-
return cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype);
2412+
wiphy_lock(wiphy);
2413+
ret = cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype);
2414+
wiphy_unlock(wiphy);
2415+
2416+
return ret;
23912417
case NL80211_IFTYPE_STATION:
23922418
case NL80211_IFTYPE_P2P_CLIENT:
23932419
return cfg80211_chandef_usable(wiphy, &chandef,

0 commit comments

Comments
 (0)