summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-03-18 19:25:40 -0700
committerJakub Kicinski <kuba@kernel.org>2026-03-18 19:25:41 -0700
commit7c46bd845d89ad4772573cfe0f2a56b93db75cc7 (patch)
tree2c25c3e6c5e00038829a91b7385c640cfd98f19d
parent605b52497bf89b3b154674deb135da98f916e390 (diff)
parentd5ad6ab61cbd89afdb60881f6274f74328af3ee9 (diff)
Merge tag 'wireless-2026-03-18' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless
Johannes Berg says: ==================== Just a few updates: - cfg80211: - guarantee pmsr work is cancelled - mac80211: - reject TDLS operations on non-TDLS stations - fix crash in AP_VLAN bandwidth change - fix leak or double-free on some TX preparation failures - remove keys needed for beacons _after_ stopping those - fix debugfs static branch race - avoid underflow in inactive time - fix another NULL dereference in mesh on invalid frames - ti/wlcore: avoid infinite realloc loop * tag 'wireless-2026-03-18' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless: wifi: mac80211: always free skb on ieee80211_tx_prepare_skb() failure wifi: wlcore: Return -ENOMEM instead of -EAGAIN if there is not enough headroom wifi: mac80211: fix NULL deref in mesh_matches_local() wifi: mac80211: check tdls flag in ieee80211_tdls_oper wifi: cfg80211: cancel pmsr_free_wk in cfg80211_pmsr_wdev_down wifi: mac80211: Fix static_branch_dec() underflow for aql_disable. mac80211: fix crash in ieee80211_chan_bw_change for AP_VLAN stations wifi: mac80211: use jiffies_delta_to_msecs() for sta_info inactive times wifi: mac80211: remove keys after disabling beaconing wifi: mac80211_hwsim: fully initialise PMSR capabilities ==================== Link: https://patch.msgid.link/20260318172515.381148-3-johannes@sipsolutions.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/net/wireless/ath/ath9k/channel.c6
-rw-r--r--drivers/net/wireless/mediatek/mt76/scan.c4
-rw-r--r--drivers/net/wireless/ti/wlcore/tx.c2
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim.c3
-rw-r--r--include/net/mac80211.h4
-rw-r--r--net/mac80211/cfg.c12
-rw-r--r--net/mac80211/chan.c6
-rw-r--r--net/mac80211/debugfs.c14
-rw-r--r--net/mac80211/mesh.c3
-rw-r--r--net/mac80211/sta_info.c7
-rw-r--r--net/mac80211/tdls.c2
-rw-r--r--net/mac80211/tx.c4
-rw-r--r--net/wireless/pmsr.c1
13 files changed, 36 insertions, 32 deletions
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index 121e51ce1bc0..8b27d8cc086a 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -1006,7 +1006,7 @@ static void ath_scan_send_probe(struct ath_softc *sc,
skb_set_queue_mapping(skb, IEEE80211_AC_VO);
if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, NULL))
- goto error;
+ return;
txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO];
if (ath_tx_start(sc->hw, skb, &txctl))
@@ -1119,10 +1119,8 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
skb->priority = 7;
skb_set_queue_mapping(skb, IEEE80211_AC_VO);
- if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) {
- dev_kfree_skb_any(skb);
+ if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta))
return false;
- }
break;
default:
return false;
diff --git a/drivers/net/wireless/mediatek/mt76/scan.c b/drivers/net/wireless/mediatek/mt76/scan.c
index ff9176cdee3d..63b0447e55c1 100644
--- a/drivers/net/wireless/mediatek/mt76/scan.c
+++ b/drivers/net/wireless/mediatek/mt76/scan.c
@@ -63,10 +63,8 @@ mt76_scan_send_probe(struct mt76_dev *dev, struct cfg80211_ssid *ssid)
rcu_read_lock();
- if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL)) {
- ieee80211_free_txskb(phy->hw, skb);
+ if (!ieee80211_tx_prepare_skb(phy->hw, vif, skb, band, NULL))
goto out;
- }
info = IEEE80211_SKB_CB(skb);
if (req->no_cck)
diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c
index 6241866d39df..75cfbcfb7626 100644
--- a/drivers/net/wireless/ti/wlcore/tx.c
+++ b/drivers/net/wireless/ti/wlcore/tx.c
@@ -210,7 +210,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif,
if (skb_headroom(skb) < (total_len - skb->len) &&
pskb_expand_head(skb, (total_len - skb->len), 0, GFP_ATOMIC)) {
wl1271_free_tx_id(wl, id);
- return -EAGAIN;
+ return -ENOMEM;
}
desc = skb_push(skb, total_len - skb->len);
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index e89173f91637..1b6e55eb81a2 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -3021,7 +3021,6 @@ static void hw_scan_work(struct work_struct *work)
hwsim->tmp_chan->band,
NULL)) {
rcu_read_unlock();
- kfree_skb(probe);
continue;
}
@@ -6489,7 +6488,7 @@ static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info)
if (info->attrs[HWSIM_ATTR_PMSR_SUPPORT]) {
struct cfg80211_pmsr_capabilities *pmsr_capa;
- pmsr_capa = kmalloc_obj(*pmsr_capa);
+ pmsr_capa = kzalloc_obj(*pmsr_capa);
if (!pmsr_capa) {
ret = -ENOMEM;
goto out_free;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 7f9d96939a4e..adce2144a678 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -7407,7 +7407,9 @@ void ieee80211_report_wowlan_wakeup(struct ieee80211_vif *vif,
* @band: the band to transmit on
* @sta: optional pointer to get the station to send the frame to
*
- * Return: %true if the skb was prepared, %false otherwise
+ * Return: %true if the skb was prepared, %false otherwise.
+ * On failure, the skb is freed by this function; callers must not
+ * free it again.
*
* Note: must be called under RCU lock
*/
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b92b4a5c2636..b85375ceb575 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1904,12 +1904,6 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
__sta_info_flush(sdata, true, link_id, NULL);
- ieee80211_remove_link_keys(link, &keys);
- if (!list_empty(&keys)) {
- synchronize_net();
- ieee80211_free_key_list(local, &keys);
- }
-
ieee80211_stop_mbssid(sdata);
RCU_INIT_POINTER(link_conf->tx_bss_conf, NULL);
@@ -1921,6 +1915,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
ieee80211_link_info_change_notify(sdata, link,
BSS_CHANGED_BEACON_ENABLED);
+ ieee80211_remove_link_keys(link, &keys);
+ if (!list_empty(&keys)) {
+ synchronize_net();
+ ieee80211_free_key_list(local, &keys);
+ }
+
if (sdata->wdev.links[link_id].cac_started) {
chandef = link_conf->chanreq.oper;
wiphy_hrtimer_work_cancel(wiphy, &link->dfs_cac_timer_work);
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 4447cf03c41b..05f45e66999b 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -561,14 +561,16 @@ static void ieee80211_chan_bw_change(struct ieee80211_local *local,
rcu_read_lock();
list_for_each_entry_rcu(sta, &local->sta_list,
list) {
- struct ieee80211_sub_if_data *sdata = sta->sdata;
+ struct ieee80211_sub_if_data *sdata;
enum ieee80211_sta_rx_bandwidth new_sta_bw;
unsigned int link_id;
if (!ieee80211_sdata_running(sta->sdata))
continue;
- for (link_id = 0; link_id < ARRAY_SIZE(sta->sdata->link); link_id++) {
+ sdata = get_bss_sdata(sta->sdata);
+
+ for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
struct ieee80211_link_data *link =
rcu_dereference(sdata->link[link_id]);
struct ieee80211_bss_conf *link_conf;
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index d02f07368c51..687a66cd4943 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -320,7 +320,6 @@ static ssize_t aql_enable_read(struct file *file, char __user *user_buf,
static ssize_t aql_enable_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
- bool aql_disabled = static_key_false(&aql_disable.key);
char buf[3];
size_t len;
@@ -335,15 +334,12 @@ static ssize_t aql_enable_write(struct file *file, const char __user *user_buf,
if (len > 0 && buf[len - 1] == '\n')
buf[len - 1] = 0;
- if (buf[0] == '0' && buf[1] == '\0') {
- if (!aql_disabled)
- static_branch_inc(&aql_disable);
- } else if (buf[0] == '1' && buf[1] == '\0') {
- if (aql_disabled)
- static_branch_dec(&aql_disable);
- } else {
+ if (buf[0] == '0' && buf[1] == '\0')
+ static_branch_enable(&aql_disable);
+ else if (buf[0] == '1' && buf[1] == '\0')
+ static_branch_disable(&aql_disable);
+ else
return -EINVAL;
- }
return count;
}
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 28624e57aa49..8fdbdf9ba2a9 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -79,6 +79,9 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
* - MDA enabled
* - Power management control on fc
*/
+ if (!ie->mesh_config)
+ return false;
+
if (!(ifmsh->mesh_id_len == ie->mesh_id_len &&
memcmp(ifmsh->mesh_id, ie->mesh_id, ie->mesh_id_len) == 0 &&
(ifmsh->mesh_pp_id == ie->mesh_config->meshconf_psel) &&
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index 6dc22f1593be..dd51a578fbc5 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -2782,7 +2782,9 @@ static void sta_set_link_sinfo(struct sta_info *sta,
}
link_sinfo->inactive_time =
- jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta, link_id));
+ jiffies_delta_to_msecs(jiffies -
+ ieee80211_sta_last_active(sta,
+ link_id));
if (!(link_sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) |
BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) {
@@ -3015,7 +3017,8 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,
sinfo->connected_time = ktime_get_seconds() - sta->last_connected;
sinfo->assoc_at = sta->assoc_at;
sinfo->inactive_time =
- jiffies_to_msecs(jiffies - ieee80211_sta_last_active(sta, -1));
+ jiffies_delta_to_msecs(jiffies -
+ ieee80211_sta_last_active(sta, -1));
if (!(sinfo->filled & (BIT_ULL(NL80211_STA_INFO_TX_BYTES64) |
BIT_ULL(NL80211_STA_INFO_TX_BYTES)))) {
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c
index dbbfe2d6842f..1dca2fae05a5 100644
--- a/net/mac80211/tdls.c
+++ b/net/mac80211/tdls.c
@@ -1449,7 +1449,7 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
}
sta = sta_info_get(sdata, peer);
- if (!sta)
+ if (!sta || !sta->sta.tdls)
return -ENOLINK;
iee80211_tdls_recalc_chanctx(sdata, sta);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 8cdbd417d7be..b7aedaab8483 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1899,8 +1899,10 @@ bool ieee80211_tx_prepare_skb(struct ieee80211_hw *hw,
struct ieee80211_tx_data tx;
struct sk_buff *skb2;
- if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP)
+ if (ieee80211_tx_prepare(sdata, &tx, NULL, skb) == TX_DROP) {
+ kfree_skb(skb);
return false;
+ }
info->band = band;
info->control.vif = vif;
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index 44bd88c9ea66..50e8e19aa366 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -664,6 +664,7 @@ void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
}
spin_unlock_bh(&wdev->pmsr_lock);
+ cancel_work_sync(&wdev->pmsr_free_wk);
if (found)
cfg80211_pmsr_process_abort(wdev);