Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'wireless-2026-03-26' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless

Johannes Berg says:

====================
Couple more fixes:

- virt_wifi: remove SET_NETDEV_DEV to avoid UAF on teardown
- iwlwifi:
- fix (some) devices that don't have 6 GHz (WiFi6E)
- fix potential OOB read of firmware notification
- set WiFi generation for firmware to avoid packet drops
- fix multi-link scan timing
- wilc1000: fix integer overflow
- ath11k/ath12k: fix TID during A-MPDU session teardown
- wl1251: don't trust firmware TX status response index

* tag 'wireless-2026-03-26' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless:
wifi: virt_wifi: remove SET_NETDEV_DEV to avoid use-after-free
wifi: iwlwifi: mvm: fix potential out-of-bounds read in iwl_mvm_nd_match_info_handler()
wifi: wl1251: validate packet IDs before indexing tx_frames
wifi: wilc1000: fix u8 overflow in SSID scan buffer size calculation
wifi: ath12k: Pass the correct value of each TID during a stop AMPDU session
wifi: ath11k: Pass the correct value of each TID during a stop AMPDU session
wifi: iwlwifi: mld: correctly set wifi generation data
wifi: iwlwifi: mvm: don't send a 6E related command when not supported
wifi: iwlwifi: mld: Fix MLO scan timing
====================

Link: https://patch.msgid.link/20260326093329.77815-3-johannes@sipsolutions.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+163 -56
+7 -8
drivers/net/wireless/ath/ath11k/dp_rx.c
··· 1 1 // SPDX-License-Identifier: BSD-3-Clause-Clear 2 2 /* 3 3 * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. 4 - * Copyright (c) 2021-2025 Qualcomm Innovation Center, Inc. All rights reserved. 4 + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 5 5 */ 6 6 7 7 #include <linux/ieee80211.h> ··· 1110 1110 struct ath11k_base *ab = ar->ab; 1111 1111 struct ath11k_peer *peer; 1112 1112 struct ath11k_sta *arsta = ath11k_sta_to_arsta(params->sta); 1113 + struct dp_rx_tid *rx_tid; 1113 1114 int vdev_id = arsta->arvif->vdev_id; 1114 - dma_addr_t paddr; 1115 - bool active; 1116 1115 int ret; 1117 1116 1118 1117 spin_lock_bh(&ab->base_lock); ··· 1123 1124 return -ENOENT; 1124 1125 } 1125 1126 1126 - paddr = peer->rx_tid[params->tid].paddr; 1127 - active = peer->rx_tid[params->tid].active; 1127 + rx_tid = &peer->rx_tid[params->tid]; 1128 1128 1129 - if (!active) { 1129 + if (!rx_tid->active) { 1130 1130 spin_unlock_bh(&ab->base_lock); 1131 1131 return 0; 1132 1132 } 1133 1133 1134 - ret = ath11k_peer_rx_tid_reo_update(ar, peer, peer->rx_tid, 1, 0, false); 1134 + ret = ath11k_peer_rx_tid_reo_update(ar, peer, rx_tid, 1, 0, false); 1135 1135 spin_unlock_bh(&ab->base_lock); 1136 1136 if (ret) { 1137 1137 ath11k_warn(ab, "failed to update reo for rx tid %d: %d\n", ··· 1139 1141 } 1140 1142 1141 1143 ret = ath11k_wmi_peer_rx_reorder_queue_setup(ar, vdev_id, 1142 - params->sta->addr, paddr, 1144 + params->sta->addr, 1145 + rx_tid->paddr, 1143 1146 params->tid, 1, 1); 1144 1147 if (ret) 1145 1148 ath11k_warn(ab, "failed to send wmi to delete rx tid %d\n",
+3 -1
drivers/net/wireless/ath/ath12k/dp_rx.c
··· 735 735 struct ath12k_dp *dp = ath12k_ab_to_dp(ab); 736 736 struct ath12k_dp_link_peer *peer; 737 737 struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta); 738 + struct ath12k_dp_rx_tid *rx_tid; 738 739 struct ath12k_link_sta *arsta; 739 740 int vdev_id; 740 741 bool active; ··· 771 770 return 0; 772 771 } 773 772 774 - ret = ath12k_dp_arch_peer_rx_tid_reo_update(dp, peer, peer->dp_peer->rx_tid, 773 + rx_tid = &peer->dp_peer->rx_tid[params->tid]; 774 + ret = ath12k_dp_arch_peer_rx_tid_reo_update(dp, peer, rx_tid, 775 775 1, 0, false); 776 776 spin_unlock_bh(&dp->dp_lock); 777 777 if (ret) {
+5
drivers/net/wireless/intel/iwlwifi/fw/api/commands.h
··· 297 297 SCAN_OFFLOAD_UPDATE_PROFILES_CMD = 0x6E, 298 298 299 299 /** 300 + * @SCAN_START_NOTIFICATION_UMAC: uses &struct iwl_umac_scan_start 301 + */ 302 + SCAN_START_NOTIFICATION_UMAC = 0xb2, 303 + 304 + /** 300 305 * @MATCH_FOUND_NOTIFICATION: scan match found 301 306 */ 302 307 MATCH_FOUND_NOTIFICATION = 0xd9,
+10
drivers/net/wireless/intel/iwlwifi/fw/api/scan.h
··· 1157 1157 }; 1158 1158 1159 1159 /** 1160 + * struct iwl_umac_scan_start - scan start notification 1161 + * @uid: scan id, &enum iwl_umac_scan_uid_offsets 1162 + * @reserved: for future use 1163 + */ 1164 + struct iwl_umac_scan_start { 1165 + __le32 uid; 1166 + __le32 reserved; 1167 + } __packed; /* SCAN_START_UMAC_API_S_VER_1 */ 1168 + 1169 + /** 1160 1170 * struct iwl_umac_scan_complete - scan complete notification 1161 1171 * @uid: scan id, &enum iwl_umac_scan_uid_offsets 1162 1172 * @last_schedule: last scheduling line
+69 -32
drivers/net/wireless/intel/iwlwifi/mld/iface.c
··· 111 111 IEEE80211_HE_MAC_CAP2_ACK_EN); 112 112 } 113 113 114 - static void iwl_mld_set_he_support(struct iwl_mld *mld, 115 - struct ieee80211_vif *vif, 116 - struct iwl_mac_config_cmd *cmd) 114 + struct iwl_mld_mac_wifi_gen_sta_iter_data { 115 + struct ieee80211_vif *vif; 116 + struct iwl_mac_wifi_gen_support *support; 117 + }; 118 + 119 + static void iwl_mld_mac_wifi_gen_sta_iter(void *_data, 120 + struct ieee80211_sta *sta) 117 121 { 118 - if (vif->type == NL80211_IFTYPE_AP) 119 - cmd->wifi_gen.he_ap_support = 1; 120 - else 121 - cmd->wifi_gen.he_support = 1; 122 + struct iwl_mld_sta *mld_sta = iwl_mld_sta_from_mac80211(sta); 123 + struct iwl_mld_mac_wifi_gen_sta_iter_data *data = _data; 124 + struct ieee80211_link_sta *link_sta; 125 + unsigned int link_id; 126 + 127 + if (mld_sta->vif != data->vif) 128 + return; 129 + 130 + for_each_sta_active_link(data->vif, sta, link_sta, link_id) { 131 + if (link_sta->he_cap.has_he) 132 + data->support->he_support = 1; 133 + if (link_sta->eht_cap.has_eht) 134 + data->support->eht_support = 1; 135 + } 136 + } 137 + 138 + static void iwl_mld_set_wifi_gen(struct iwl_mld *mld, 139 + struct ieee80211_vif *vif, 140 + struct iwl_mac_wifi_gen_support *support) 141 + { 142 + struct iwl_mld_mac_wifi_gen_sta_iter_data sta_iter_data = { 143 + .vif = vif, 144 + .support = support, 145 + }; 146 + struct ieee80211_bss_conf *link_conf; 147 + unsigned int link_id; 148 + 149 + switch (vif->type) { 150 + case NL80211_IFTYPE_MONITOR: 151 + /* for sniffer, set to HW capabilities */ 152 + support->he_support = 1; 153 + support->eht_support = mld->trans->cfg->eht_supported; 154 + break; 155 + case NL80211_IFTYPE_AP: 156 + /* for AP set according to the link configs */ 157 + for_each_vif_active_link(vif, link_conf, link_id) { 158 + support->he_ap_support |= link_conf->he_support; 159 + support->eht_support |= link_conf->eht_support; 160 + } 161 + break; 162 + default: 163 + /* 164 + * If we have MLO enabled, then the firmware needs to enable 165 + * address translation for the station(s) we add. That depends 166 + * on having EHT enabled in firmware, which in turn depends on 167 + * mac80211 in the iteration below. 168 + * However, mac80211 doesn't enable capabilities on the AP STA 169 + * until it has parsed the association response successfully, 170 + * so set EHT (and HE as a pre-requisite for EHT) when the vif 171 + * is an MLD. 172 + */ 173 + if (ieee80211_vif_is_mld(vif)) { 174 + support->he_support = 1; 175 + support->eht_support = 1; 176 + } 177 + 178 + ieee80211_iterate_stations_mtx(mld->hw, 179 + iwl_mld_mac_wifi_gen_sta_iter, 180 + &sta_iter_data); 181 + break; 182 + } 122 183 } 123 184 124 185 /* fill the common part for all interface types */ ··· 189 128 u32 action) 190 129 { 191 130 struct iwl_mld_vif *mld_vif = iwl_mld_vif_from_mac80211(vif); 192 - struct ieee80211_bss_conf *link_conf; 193 - unsigned int link_id; 194 131 195 132 lockdep_assert_wiphy(mld->wiphy); 196 133 ··· 206 147 cmd->nic_not_ack_enabled = 207 148 cpu_to_le32(!iwl_mld_is_nic_ack_enabled(mld, vif)); 208 149 209 - /* If we have MLO enabled, then the firmware needs to enable 210 - * address translation for the station(s) we add. That depends 211 - * on having EHT enabled in firmware, which in turn depends on 212 - * mac80211 in the code below. 213 - * However, mac80211 doesn't enable HE/EHT until it has parsed 214 - * the association response successfully, so just skip all that 215 - * and enable both when we have MLO. 216 - */ 217 - if (ieee80211_vif_is_mld(vif)) { 218 - iwl_mld_set_he_support(mld, vif, cmd); 219 - cmd->wifi_gen.eht_support = 1; 220 - return; 221 - } 222 - 223 - for_each_vif_active_link(vif, link_conf, link_id) { 224 - if (!link_conf->he_support) 225 - continue; 226 - 227 - iwl_mld_set_he_support(mld, vif, cmd); 228 - 229 - /* EHT, if supported, was already set above */ 230 - break; 231 - } 150 + iwl_mld_set_wifi_gen(mld, vif, &cmd->wifi_gen); 232 151 } 233 152 234 153 static void iwl_mld_fill_mac_cmd_sta(struct iwl_mld *mld,
+19
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c
··· 1761 1761 1762 1762 if (vif->type == NL80211_IFTYPE_STATION) 1763 1763 iwl_mld_link_set_2mhz_block(mld, vif, sta); 1764 + 1765 + if (sta->tdls) { 1766 + /* 1767 + * update MAC since wifi generation flags may change, 1768 + * we also update MAC on association to the AP via the 1769 + * vif assoc change 1770 + */ 1771 + iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_MODIFY); 1772 + } 1773 + 1764 1774 /* Now the link_sta's capabilities are set, update the FW */ 1765 1775 iwl_mld_config_tlc(mld, vif, sta); 1766 1776 ··· 1882 1872 if (sta->tdls && iwl_mld_tdls_sta_count(mld) == 0) { 1883 1873 /* just removed last TDLS STA, so enable PM */ 1884 1874 iwl_mld_update_mac_power(mld, vif, false); 1875 + } 1876 + 1877 + if (sta->tdls) { 1878 + /* 1879 + * update MAC since wifi generation flags may change, 1880 + * we also update MAC on disassociation to the AP via 1881 + * the vif assoc change 1882 + */ 1883 + iwl_mld_mac_fw_action(mld, vif, FW_CTXT_ACTION_MODIFY); 1885 1884 } 1886 1885 } else { 1887 1886 return -EINVAL;
+1
drivers/net/wireless/intel/iwlwifi/mld/mld.c
··· 171 171 HCMD_NAME(MISSED_BEACONS_NOTIFICATION), 172 172 HCMD_NAME(MAC_PM_POWER_TABLE), 173 173 HCMD_NAME(MFUART_LOAD_NOTIFICATION), 174 + HCMD_NAME(SCAN_START_NOTIFICATION_UMAC), 174 175 HCMD_NAME(RSS_CONFIG_CMD), 175 176 HCMD_NAME(SCAN_ITERATION_COMPLETE_UMAC), 176 177 HCMD_NAME(REPLY_RX_MPDU_CMD),
+2 -2
drivers/net/wireless/intel/iwlwifi/mld/mlo.c
··· 739 739 740 740 /* Ignore any BSS that was not seen in the last MLO scan */ 741 741 if (ktime_before(link_conf->bss->ts_boottime, 742 - mld->scan.last_mlo_scan_time)) 742 + mld->scan.last_mlo_scan_start_time)) 743 743 continue; 744 744 745 745 data[n_data].link_id = link_id; ··· 945 945 if (!mld_vif->authorized || hweight16(usable_links) <= 1) 946 946 return; 947 947 948 - if (WARN(ktime_before(mld->scan.last_mlo_scan_time, 948 + if (WARN(ktime_before(mld->scan.last_mlo_scan_start_time, 949 949 ktime_sub_ns(ktime_get_boottime_ns(), 950 950 5ULL * NSEC_PER_SEC)), 951 951 "Last MLO scan was too long ago, can't select links\n"))
+5
drivers/net/wireless/intel/iwlwifi/mld/notif.c
··· 287 287 * at least enough bytes to cover the structure listed in the CMD_VER_ENTRY. 288 288 */ 289 289 290 + CMD_VERSIONS(scan_start_notif, 291 + CMD_VER_ENTRY(1, iwl_umac_scan_start)) 290 292 CMD_VERSIONS(scan_complete_notif, 291 293 CMD_VER_ENTRY(1, iwl_umac_scan_complete)) 292 294 CMD_VERSIONS(scan_iter_complete_notif, ··· 362 360 link_id) 363 361 DEFINE_SIMPLE_CANCELLATION(roc, iwl_roc_notif, activity) 364 362 DEFINE_SIMPLE_CANCELLATION(scan_complete, iwl_umac_scan_complete, uid) 363 + DEFINE_SIMPLE_CANCELLATION(scan_start, iwl_umac_scan_start, uid) 365 364 DEFINE_SIMPLE_CANCELLATION(probe_resp_data, iwl_probe_resp_data_notif, 366 365 mac_id) 367 366 DEFINE_SIMPLE_CANCELLATION(uapsd_misbehaving_ap, iwl_uapsd_misbehaving_ap_notif, ··· 405 402 RX_HANDLER_SYNC) 406 403 RX_HANDLER_NO_OBJECT(LEGACY_GROUP, BA_NOTIF, compressed_ba_notif, 407 404 RX_HANDLER_SYNC) 405 + RX_HANDLER_OF_SCAN(LEGACY_GROUP, SCAN_START_NOTIFICATION_UMAC, 406 + scan_start_notif) 408 407 RX_HANDLER_OF_SCAN(LEGACY_GROUP, SCAN_COMPLETE_UMAC, 409 408 scan_complete_notif) 410 409 RX_HANDLER_NO_OBJECT(LEGACY_GROUP, SCAN_ITERATION_COMPLETE_UMAC,
+27 -3
drivers/net/wireless/intel/iwlwifi/mld/scan.c
··· 473 473 params->flags & NL80211_SCAN_FLAG_COLOCATED_6GHZ) 474 474 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_TRIGGER_UHB_SCAN; 475 475 476 + if (scan_status == IWL_MLD_SCAN_INT_MLO) 477 + flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_NTF_START; 478 + 476 479 if (params->enable_6ghz_passive) 477 480 flags |= IWL_UMAC_SCAN_GEN_FLAGS_V2_6GHZ_PASSIVE_SCAN; 478 481 ··· 1820 1817 ret = _iwl_mld_single_scan_start(mld, vif, req, &ies, 1821 1818 IWL_MLD_SCAN_INT_MLO); 1822 1819 1823 - if (!ret) 1824 - mld->scan.last_mlo_scan_time = ktime_get_boottime_ns(); 1825 - 1826 1820 IWL_DEBUG_SCAN(mld, "Internal MLO scan: ret=%d\n", ret); 1827 1821 } 1828 1822 ··· 1902 1902 { 1903 1903 IWL_DEBUG_SCAN(mld, "Scheduled scan results\n"); 1904 1904 ieee80211_sched_scan_results(mld->hw); 1905 + } 1906 + 1907 + void iwl_mld_handle_scan_start_notif(struct iwl_mld *mld, 1908 + struct iwl_rx_packet *pkt) 1909 + { 1910 + struct iwl_umac_scan_complete *notif = (void *)pkt->data; 1911 + u32 uid = le32_to_cpu(notif->uid); 1912 + 1913 + if (IWL_FW_CHECK(mld, uid >= ARRAY_SIZE(mld->scan.uid_status), 1914 + "FW reports out-of-range scan UID %d\n", uid)) 1915 + return; 1916 + 1917 + if (IWL_FW_CHECK(mld, !(mld->scan.uid_status[uid] & mld->scan.status), 1918 + "FW reports scan UID %d we didn't trigger\n", uid)) 1919 + return; 1920 + 1921 + IWL_DEBUG_SCAN(mld, "Scan started: uid=%u type=%u\n", uid, 1922 + mld->scan.uid_status[uid]); 1923 + if (IWL_FW_CHECK(mld, mld->scan.uid_status[uid] != IWL_MLD_SCAN_INT_MLO, 1924 + "FW reports scan start notification %d we didn't trigger\n", 1925 + mld->scan.uid_status[uid])) 1926 + return; 1927 + 1928 + mld->scan.last_mlo_scan_start_time = ktime_get_boottime_ns(); 1905 1929 } 1906 1930 1907 1931 void iwl_mld_handle_scan_complete_notif(struct iwl_mld *mld,
+6 -3
drivers/net/wireless/intel/iwlwifi/mld/scan.h
··· 27 27 void iwl_mld_handle_match_found_notif(struct iwl_mld *mld, 28 28 struct iwl_rx_packet *pkt); 29 29 30 + void iwl_mld_handle_scan_start_notif(struct iwl_mld *mld, 31 + struct iwl_rx_packet *pkt); 32 + 30 33 void iwl_mld_handle_scan_complete_notif(struct iwl_mld *mld, 31 34 struct iwl_rx_packet *pkt); 32 35 ··· 117 114 * in jiffies. 118 115 * @last_start_time_jiffies: stores the last start time in jiffies 119 116 * (interface up/reset/resume). 120 - * @last_mlo_scan_time: start time of the last MLO scan in nanoseconds since 121 - * boot. 117 + * @last_mlo_scan_start_time: start time of the last MLO scan in nanoseconds 118 + * since boot. 122 119 */ 123 120 struct iwl_mld_scan { 124 121 /* Add here fields that need clean up on restart */ ··· 139 136 void *cmd; 140 137 unsigned long last_6ghz_passive_jiffies; 141 138 unsigned long last_start_time_jiffies; 142 - u64 last_mlo_scan_time; 139 + u64 last_mlo_scan_start_time; 143 140 }; 144 141 145 142 /**
+1 -1
drivers/net/wireless/intel/iwlwifi/mvm/d3.c
··· 2807 2807 if (IS_ERR_OR_NULL(vif)) 2808 2808 return; 2809 2809 2810 - if (len < sizeof(struct iwl_scan_offload_match_info)) { 2810 + if (len < sizeof(struct iwl_scan_offload_match_info) + matches_len) { 2811 2811 IWL_ERR(mvm, "Invalid scan match info notification\n"); 2812 2812 return; 2813 2813 }
+2 -1
drivers/net/wireless/intel/iwlwifi/mvm/fw.c
··· 470 470 .dataflags[0] = IWL_HCMD_DFL_NOCOPY, 471 471 }; 472 472 473 - if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210) { 473 + if (mvm->trans->mac_cfg->device_family < IWL_DEVICE_FAMILY_AX210 || 474 + !mvm->trans->cfg->uhb_supported) { 474 475 IWL_DEBUG_RADIO(mvm, "UATS feature is not supported\n"); 475 476 return; 476 477 }
+1 -1
drivers/net/wireless/microchip/wilc1000/hif.c
··· 163 163 u32 index = 0; 164 164 u32 i, scan_timeout; 165 165 u8 *buffer; 166 - u8 valuesize = 0; 166 + u32 valuesize = 0; 167 167 u8 *search_ssid_vals = NULL; 168 168 const u8 ch_list_len = request->n_channels; 169 169 struct host_if_drv *hif_drv = vif->hif_drv;
+5 -3
drivers/net/wireless/ti/wl1251/tx.c
··· 402 402 int hdrlen; 403 403 u8 *frame; 404 404 405 - skb = wl->tx_frames[result->id]; 406 - if (skb == NULL) { 407 - wl1251_error("SKB for packet %d is NULL", result->id); 405 + if (unlikely(result->id >= ARRAY_SIZE(wl->tx_frames) || 406 + wl->tx_frames[result->id] == NULL)) { 407 + wl1251_error("invalid packet id %u", result->id); 408 408 return; 409 409 } 410 + 411 + skb = wl->tx_frames[result->id]; 410 412 411 413 info = IEEE80211_SKB_CB(skb); 412 414
-1
drivers/net/wireless/virtual/virt_wifi.c
··· 557 557 eth_hw_addr_inherit(dev, priv->lowerdev); 558 558 netif_stacked_transfer_operstate(priv->lowerdev, dev); 559 559 560 - SET_NETDEV_DEV(dev, &priv->lowerdev->dev); 561 560 dev->ieee80211_ptr = kzalloc_obj(*dev->ieee80211_ptr); 562 561 563 562 if (!dev->ieee80211_ptr) {