Quite a number of fixes now:

- mac80211
    - remove HT NSS validation to work with broken APs
      (with a kunit fix now)
    - remove 'static' that could cause races
    - check station link lookup before further processing
    - fix use-after-free due to delete in list iteration
    - remove AP station on assoc failures to fix crashes
  - ath12k
    - fix OF node refcount imbalance
    - fix queue flush ("REO update") in MLO
    - fix RCU assert
  - ath12k:
    - fix Kconfig with POWER_SEQUENCING
    - fix WMI buffer leaks on error conditions
    - don't use uninitialized stack data when processing RSSI events
    - fix logic for determining the peer ID in the RX path
  - ath5k: fix a potential stack buffer overwrite
  - rsi: fix thread lifetime race
  - brcmfmac: fix potential UAF
  - nl80211:
    - stricter permissions/checks for PMK and netns
    - fix netlink policy vs. code type confusion
  - cw1200: revert a broken locking change
  - various fixes to not trust values from firmware
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEpeA8sTs3M8SN2hR410qiO8sPaAAFAmn7Hj8ACgkQ10qiO8sP
 aACOiA//QZXrPPCxJmCkThP9DUYv2sxRAbTEEJLRJcXZODWJ7nBDn7tdM/nvOJmm
 8Y0v/+DqhqCVJ4Zkvh4u8S6Z7tGt83LKi+j8dAMoZw+Bn2Qq5mFvOK9ENOk4pfmB
 isVKTDFxAgbgtkClo3eygK6z9KuClY5JbQ9wmcE450cjuIYQ4z6UmNTeHcnsombX
 flvKX8JXINwolX1MrL5t+qMZ14bd+BL0Ui9VkvxxuECvdrQemhf7iBfCELfs8Q2r
 PxQcfPq5zIKPTqAcR50HPV/1YDPk66tG3P3NxA/DvAYUXXc7XHr0RYD5IJ/HYafM
 APVHA0XU4aoyDLiWSrSDj1WoRs+MYIlUl7BRdrE4ABenwB2lGTkfdUYuq9dQKPtQ
 Ku92UATOrXdMEZH7TVnme4RbtotWH+nUCw1os/OyoGNfL3czFJIqntUXVjLuUB4e
 Bo3qWtTHVmu3B+OJlNsKiiz8d4L5FxHFnaSKA4MkEfNrZsSuV4N4Sl6PsWMWvJUa
 G/EnUJiDKBaFO0lDAZRtYFr8CVxRBBlCKfCQs+mwxLXHjB7BZW3eA5Ps9qWq4krV
 VbNwDTBwIPdWz12UfHmSpkoIPCbrTcbvdUM7uNwJKr8nuulve2lkZo73LEhEX8k2
 jdXxDndaQyWX9Lmx5b9NpA/xRqxRlgFN7U3ZV8ntH4d9IsQOzZM=
 =RBbh
 -----END PGP SIGNATURE-----

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

Johannes Berg says:

====================
Quite a number of fixes now:
 - mac80211
   - remove HT NSS validation to work with broken APs
     (with a kunit fix now)
   - remove 'static' that could cause races
   - check station link lookup before further processing
   - fix use-after-free due to delete in list iteration
   - remove AP station on assoc failures to fix crashes
 - ath12k
   - fix OF node refcount imbalance
   - fix queue flush ("REO update") in MLO
   - fix RCU assert
 - ath12k:
   - fix Kconfig with POWER_SEQUENCING
   - fix WMI buffer leaks on error conditions
   - don't use uninitialized stack data when processing RSSI events
   - fix logic for determining the peer ID in the RX path
 - ath5k: fix a potential stack buffer overwrite
 - rsi: fix thread lifetime race
 - brcmfmac: fix potential UAF
 - nl80211:
   - stricter permissions/checks for PMK and netns
   - fix netlink policy vs. code type confusion
 - cw1200: revert a broken locking change
 - various fixes to not trust values from firmware

* tag 'wireless-2026-05-06' of https://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless: (25 commits)
  wifi: nl80211: re-check wiphy netns in nl80211_prepare_wdev_dump() continuation
  wifi: nl80211: require CAP_NET_ADMIN over the target netns in SET_WIPHY_NETNS
  wifi: nl80211: fix NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST usage
  wifi: mac80211: remove station if connection prep fails
  wifi: mac80211: use safe list iteration in radar detect work
  wifi: libertas: notify firmware load wait on disconnect
  wifi: ath5k: do not access array OOB
  wifi: ath12k: fix peer_id usage in normal RX path
  wifi: ath12k: initialize RSSI dBm conversion event state
  wifi: ath12k: fix leak in some ath12k_wmi_xxx() functions
  wifi: cw1200: Revert "Fix locking in error paths"
  wifi: mac80211: tests: mark HT check strict
  wifi: rsi: fix kthread lifetime race between self-exit and external-stop
  wifi: mac80211: drop stray 'static' from fast-RX rx_result
  wifi: mac80211: check ieee80211_rx_data_set_link return in pubsta MLO path
  wifi: nl80211: require admin perm on SET_PMK / DEL_PMK
  wifi: libertas: fix integer underflow in process_cmdrequest()
  wifi: b43legacy: enforce bounds check on firmware key index in RX path
  wifi: b43: enforce bounds check on firmware key index in b43_rx()
  wifi: brcmfmac: Fix potential use-after-free issue when stopping watchdog task
  ...
====================

Link: https://patch.msgid.link/20260506110325.219675-3-johannes@sipsolutions.net
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2026-05-06 07:29:31 -07:00
commit b89e0100a5
19 changed files with 208 additions and 70 deletions

View File

@ -46,6 +46,7 @@ config ATH10K_SNOC
depends on ARCH_QCOM || COMPILE_TEST
depends on QCOM_SMEM
depends on QCOM_RPROC_COMMON || QCOM_RPROC_COMMON=n
select POWER_SEQUENCING
select QCOM_SCM
select QCOM_QMI_HELPERS
help

View File

@ -1838,10 +1838,22 @@ static struct ath12k_hw_group *ath12k_core_hw_group_alloc(struct ath12k_base *ab
return ag;
}
static void ath12k_core_free_wsi_info(struct ath12k_hw_group *ag)
{
int i;
for (i = 0; i < ag->num_devices; i++) {
of_node_put(ag->wsi_node[i]);
ag->wsi_node[i] = NULL;
}
ag->num_devices = 0;
}
static void ath12k_core_hw_group_free(struct ath12k_hw_group *ag)
{
mutex_lock(&ath12k_hw_group_mutex);
ath12k_core_free_wsi_info(ag);
list_del(&ag->list);
kfree(ag);
@ -1867,52 +1879,59 @@ static struct ath12k_hw_group *ath12k_core_hw_group_find_by_dt(struct ath12k_bas
static int ath12k_core_get_wsi_info(struct ath12k_hw_group *ag,
struct ath12k_base *ab)
{
struct device_node *wsi_dev = ab->dev->of_node, *next_wsi_dev;
struct device_node *tx_endpoint, *next_rx_endpoint;
int device_count = 0;
struct device_node *next_wsi_dev;
int device_count = 0, ret = 0;
struct device_node *wsi_dev;
next_wsi_dev = wsi_dev;
if (!next_wsi_dev)
wsi_dev = of_node_get(ab->dev->of_node);
if (!wsi_dev)
return -ENODEV;
do {
ag->wsi_node[device_count] = next_wsi_dev;
if (device_count >= ATH12K_MAX_DEVICES) {
ath12k_warn(ab, "device count in DT %d is more than limit %d\n",
device_count, ATH12K_MAX_DEVICES);
ret = -EINVAL;
break;
}
tx_endpoint = of_graph_get_endpoint_by_regs(next_wsi_dev, 0, -1);
ag->wsi_node[device_count++] = of_node_get(wsi_dev);
struct device_node *tx_endpoint __free(device_node) =
of_graph_get_endpoint_by_regs(wsi_dev, 0, -1);
if (!tx_endpoint) {
of_node_put(next_wsi_dev);
return -ENODEV;
ret = -ENODEV;
break;
}
next_rx_endpoint = of_graph_get_remote_endpoint(tx_endpoint);
struct device_node *next_rx_endpoint __free(device_node) =
of_graph_get_remote_endpoint(tx_endpoint);
if (!next_rx_endpoint) {
of_node_put(next_wsi_dev);
of_node_put(tx_endpoint);
return -ENODEV;
ret = -ENODEV;
break;
}
of_node_put(tx_endpoint);
of_node_put(next_wsi_dev);
next_wsi_dev = of_graph_get_port_parent(next_rx_endpoint);
if (!next_wsi_dev) {
of_node_put(next_rx_endpoint);
return -ENODEV;
ret = -ENODEV;
break;
}
of_node_put(next_rx_endpoint);
of_node_put(wsi_dev);
wsi_dev = next_wsi_dev;
} while (ab->dev->of_node != wsi_dev);
device_count++;
if (device_count > ATH12K_MAX_DEVICES) {
ath12k_warn(ab, "device count in DT %d is more than limit %d\n",
device_count, ATH12K_MAX_DEVICES);
of_node_put(next_wsi_dev);
return -EINVAL;
if (ret) {
while (--device_count >= 0) {
of_node_put(ag->wsi_node[device_count]);
ag->wsi_node[device_count] = NULL;
}
} while (wsi_dev != next_wsi_dev);
of_node_put(next_wsi_dev);
of_node_put(wsi_dev);
return ret;
}
of_node_put(wsi_dev);
ag->num_devices = device_count;
return 0;
@ -1983,9 +2002,9 @@ static struct ath12k_hw_group *ath12k_core_hw_group_assign(struct ath12k_base *a
ath12k_core_get_wsi_index(ag, ab)) {
ath12k_dbg(ab, ATH12K_DBG_BOOT,
"unable to get wsi info from dt, grouping single device");
ath12k_core_free_wsi_info(ag);
ag->id = ATH12K_INVALID_GROUP_ID;
ag->num_devices = 1;
memset(ag->wsi_node, 0, sizeof(ag->wsi_node));
wsi->index = 0;
}

View File

@ -565,6 +565,9 @@ static int ath12k_dp_prepare_reo_update_elem(struct ath12k_dp *dp,
lockdep_assert_held(&dp->dp_lock);
if (!peer->primary_link)
return 0;
elem = kzalloc_obj(*elem, GFP_ATOMIC);
if (!elem)
return -ENOMEM;
@ -1337,7 +1340,7 @@ void ath12k_dp_rx_deliver_msdu(struct ath12k_pdev_dp *dp_pdev, struct napi_struc
bool is_mcbc = rxcb->is_mcbc;
bool is_eapol = rxcb->is_eapol;
peer = ath12k_dp_peer_find_by_peerid(dp_pdev, rx_info->peer_id);
peer = ath12k_dp_peer_find_by_peerid(dp_pdev, rxcb->peer_id);
pubsta = peer ? peer->sta : NULL;

View File

@ -788,7 +788,7 @@ struct ath12k_link_vif *ath12k_mac_get_arvif(struct ath12k *ar, u32 vdev_id)
/* To use the arvif returned, caller must have held rcu read lock.
*/
WARN_ON(!rcu_read_lock_any_held());
lockdep_assert_in_rcu_read_lock();
arvif_iter.vdev_id = vdev_id;
arvif_iter.ar = ar;

View File

@ -123,7 +123,7 @@ static void ath12k_p2p_noa_update_vdev_iter(void *data, u8 *mac,
struct ath12k_p2p_noa_arg *arg = data;
struct ath12k_link_vif *arvif;
WARN_ON(!rcu_read_lock_any_held());
lockdep_assert_in_rcu_read_lock();
arvif = &ahvif->deflink;
if (!arvif->is_created || arvif->ar != arg->ar || arvif->vdev_id != arg->vdev_id)
return;

View File

@ -9778,7 +9778,7 @@ static void
ath12k_wmi_rssi_dbm_conversion_params_info_event(struct ath12k_base *ab,
struct sk_buff *skb)
{
struct ath12k_wmi_rssi_dbm_conv_info_arg rssi_info;
struct ath12k_wmi_rssi_dbm_conv_info_arg rssi_info = {};
struct ath12k *ar;
s32 noise_floor;
u32 pdev_id;
@ -10251,7 +10251,7 @@ int ath12k_wmi_hw_data_filter_cmd(struct ath12k *ar, struct wmi_hw_data_filter_a
{
struct wmi_hw_data_filter_cmd *cmd;
struct sk_buff *skb;
int len;
int ret, len;
len = sizeof(*cmd);
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
@ -10275,7 +10275,13 @@ int ath12k_wmi_hw_data_filter_cmd(struct ath12k *ar, struct wmi_hw_data_filter_a
"wmi hw data filter enable %d filter_bitmap 0x%x\n",
arg->enable, arg->hw_filter_bitmap);
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID);
if (ret) {
ath12k_warn(ar->ab, "failed to send WMI_HW_DATA_FILTER_CMDID\n");
dev_kfree_skb(skb);
}
return ret;
}
int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar)
@ -10283,6 +10289,7 @@ int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar)
struct wmi_wow_host_wakeup_cmd *cmd;
struct sk_buff *skb;
size_t len;
int ret;
len = sizeof(*cmd);
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
@ -10295,14 +10302,20 @@ int ath12k_wmi_wow_host_wakeup_ind(struct ath12k *ar)
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow host wakeup ind\n");
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID);
if (ret) {
ath12k_warn(ar->ab, "failed to send WMI_WOW_HOSTWAKEUP_FROM_SLEEP_CMDID\n");
dev_kfree_skb(skb);
}
return ret;
}
int ath12k_wmi_wow_enable(struct ath12k *ar)
{
struct wmi_wow_enable_cmd *cmd;
struct sk_buff *skb;
int len;
int ret, len;
len = sizeof(*cmd);
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
@ -10317,7 +10330,13 @@ int ath12k_wmi_wow_enable(struct ath12k *ar)
cmd->pause_iface_config = cpu_to_le32(WOW_IFACE_PAUSE_ENABLED);
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow enable\n");
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_CMDID);
if (ret) {
ath12k_warn(ar->ab, "failed to send WMI_WOW_ENABLE_CMDID\n");
dev_kfree_skb(skb);
}
return ret;
}
int ath12k_wmi_wow_add_wakeup_event(struct ath12k *ar, u32 vdev_id,
@ -10327,6 +10346,7 @@ int ath12k_wmi_wow_add_wakeup_event(struct ath12k *ar, u32 vdev_id,
struct wmi_wow_add_del_event_cmd *cmd;
struct sk_buff *skb;
size_t len;
int ret;
len = sizeof(*cmd);
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
@ -10343,7 +10363,13 @@ int ath12k_wmi_wow_add_wakeup_event(struct ath12k *ar, u32 vdev_id,
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow add wakeup event %s enable %d vdev_id %d\n",
wow_wakeup_event(event), enable, vdev_id);
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID);
if (ret) {
ath12k_warn(ar->ab, "failed to send WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID\n");
dev_kfree_skb(skb);
}
return ret;
}
int ath12k_wmi_wow_add_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id,
@ -10356,6 +10382,7 @@ int ath12k_wmi_wow_add_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id,
struct sk_buff *skb;
void *ptr;
size_t len;
int ret;
len = sizeof(*cmd) +
sizeof(*tlv) + /* array struct */
@ -10435,7 +10462,13 @@ int ath12k_wmi_wow_add_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id,
ath12k_dbg_dump(ar->ab, ATH12K_DBG_WMI, NULL, "wow bitmask: ",
bitmap->bitmaskbuf, pattern_len);
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID);
if (ret) {
ath12k_warn(ar->ab, "failed to send WMI_WOW_ADD_WAKE_PATTERN_CMDID\n");
dev_kfree_skb(skb);
}
return ret;
}
int ath12k_wmi_wow_del_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id)
@ -10443,6 +10476,7 @@ int ath12k_wmi_wow_del_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id)
struct wmi_wow_del_pattern_cmd *cmd;
struct sk_buff *skb;
size_t len;
int ret;
len = sizeof(*cmd);
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
@ -10459,7 +10493,13 @@ int ath12k_wmi_wow_del_pattern(struct ath12k *ar, u32 vdev_id, u32 pattern_id)
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n",
vdev_id, pattern_id);
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID);
if (ret) {
ath12k_warn(ar->ab, "failed to send WMI_WOW_DEL_WAKE_PATTERN_CMDID\n");
dev_kfree_skb(skb);
}
return ret;
}
static struct sk_buff *
@ -10595,6 +10635,7 @@ int ath12k_wmi_wow_config_pno(struct ath12k *ar, u32 vdev_id,
struct wmi_pno_scan_req_arg *pno_scan)
{
struct sk_buff *skb;
int ret;
if (pno_scan->enable)
skb = ath12k_wmi_op_gen_config_pno_start(ar, vdev_id, pno_scan);
@ -10604,7 +10645,13 @@ int ath12k_wmi_wow_config_pno(struct ath12k *ar, u32 vdev_id,
if (IS_ERR_OR_NULL(skb))
return -ENOMEM;
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID);
if (ret) {
ath12k_warn(ar->ab, "failed to send WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID\n");
dev_kfree_skb(skb);
}
return ret;
}
static void ath12k_wmi_fill_ns_offload(struct ath12k *ar,
@ -10717,6 +10764,7 @@ int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
void *buf_ptr;
size_t len;
u8 ns_cnt, ns_ext_tuples = 0;
int ret;
ns_cnt = offload->ipv6_count;
@ -10752,7 +10800,13 @@ int ath12k_wmi_arp_ns_offload(struct ath12k *ar,
if (ns_ext_tuples)
ath12k_wmi_fill_ns_offload(ar, offload, &buf_ptr, enable, 1);
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID);
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID);
if (ret) {
ath12k_warn(ar->ab, "failed to send WMI_SET_ARP_NS_OFFLOAD_CMDID\n");
dev_kfree_skb(skb);
}
return ret;
}
int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
@ -10762,7 +10816,7 @@ int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
struct wmi_gtk_rekey_offload_cmd *cmd;
struct sk_buff *skb;
__le64 replay_ctr;
int len;
int ret, len;
len = sizeof(*cmd);
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
@ -10789,7 +10843,13 @@ int ath12k_wmi_gtk_rekey_offload(struct ath12k *ar,
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "offload gtk rekey vdev: %d %d\n",
arvif->vdev_id, enable);
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
if (ret) {
ath12k_warn(ar->ab, "failed to send WMI_GTK_OFFLOAD_CMDID offload\n");
dev_kfree_skb(skb);
}
return ret;
}
int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
@ -10797,7 +10857,7 @@ int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
{
struct wmi_gtk_rekey_offload_cmd *cmd;
struct sk_buff *skb;
int len;
int ret, len;
len = sizeof(*cmd);
skb = ath12k_wmi_alloc_skb(ar->wmi->wmi_ab, len);
@ -10811,7 +10871,13 @@ int ath12k_wmi_gtk_rekey_getinfo(struct ath12k *ar,
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "get gtk rekey vdev_id: %d\n",
arvif->vdev_id);
return ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
ret = ath12k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID);
if (ret) {
ath12k_warn(ar->ab, "failed to send WMI_GTK_OFFLOAD_CMDID getinfo\n");
dev_kfree_skb(skb);
}
return ret;
}
int ath12k_wmi_sta_keepalive(struct ath12k *ar,
@ -10822,6 +10888,7 @@ int ath12k_wmi_sta_keepalive(struct ath12k *ar,
struct wmi_sta_keepalive_cmd *cmd;
struct sk_buff *skb;
size_t len;
int ret;
len = sizeof(*cmd) + sizeof(*arp);
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
@ -10849,7 +10916,13 @@ int ath12k_wmi_sta_keepalive(struct ath12k *ar,
"wmi sta keepalive vdev %d enabled %d method %d interval %d\n",
arg->vdev_id, arg->enabled, arg->method, arg->interval);
return ath12k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
ret = ath12k_wmi_cmd_send(wmi, skb, WMI_STA_KEEPALIVE_CMDID);
if (ret) {
ath12k_warn(ar->ab, "failed to send WMI_STA_KEEPALIVE_CMDID\n");
dev_kfree_skb(skb);
}
return ret;
}
int ath12k_wmi_mlo_setup(struct ath12k *ar, struct wmi_mlo_setup_arg *mlo_params)

View File

@ -1738,7 +1738,8 @@ ath5k_tx_frame_completed(struct ath5k_hw *ah, struct sk_buff *skb,
}
info->status.rates[ts->ts_final_idx].count = ts->ts_final_retry;
info->status.rates[ts->ts_final_idx + 1].idx = -1;
if (ts->ts_final_idx + 1 < IEEE80211_TX_MAX_RATES)
info->status.rates[ts->ts_final_idx + 1].idx = -1;
if (unlikely(ts->ts_status)) {
ah->stats.ack_fail++;

View File

@ -702,7 +702,8 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
* key index, but the ucode passed it slightly different.
*/
keyidx = b43_kidx_to_raw(dev, keyidx);
B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key));
if (B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key)))
goto drop;
if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) {
wlhdr_len = ieee80211_hdrlen(fctl);

View File

@ -476,7 +476,8 @@ void b43legacy_rx(struct b43legacy_wldev *dev,
* key index, but the ucode passed it slightly different.
*/
keyidx = b43legacy_kidx_to_raw(dev, keyidx);
B43legacy_WARN_ON(keyidx >= dev->max_nr_keys);
if (B43legacy_WARN_ON(keyidx >= dev->max_nr_keys))
goto drop;
if (dev->key[keyidx].algorithm != B43legacy_SEC_ALGO_NONE) {
/* Remove PROTECTED flag to mark it as decrypted. */

View File

@ -2476,8 +2476,9 @@ static void brcmf_sdio_bus_stop(struct device *dev)
brcmf_dbg(TRACE, "Enter\n");
if (bus->watchdog_tsk) {
get_task_struct(bus->watchdog_tsk);
send_sig(SIGTERM, bus->watchdog_tsk, 1);
kthread_stop(bus->watchdog_tsk);
kthread_stop_put(bus->watchdog_tsk);
bus->watchdog_tsk = NULL;
}
@ -4567,8 +4568,9 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
if (bus) {
/* Stop watchdog task */
if (bus->watchdog_tsk) {
get_task_struct(bus->watchdog_tsk);
send_sig(SIGTERM, bus->watchdog_tsk, 1);
kthread_stop(bus->watchdog_tsk);
kthread_stop_put(bus->watchdog_tsk);
bus->watchdog_tsk = NULL;
}

View File

@ -310,6 +310,7 @@ static void if_usb_disconnect(struct usb_interface *intf)
struct lbs_private *priv = cardp->priv;
cardp->surprise_removed = 1;
wake_up(&cardp->fw_wq);
if (priv) {
lbs_stop_card(priv);
@ -633,9 +634,10 @@ static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff,
unsigned long flags;
u8 i;
if (recvlength > LBS_CMD_BUFFER_SIZE) {
if (recvlength < MESSAGE_HEADER_LEN ||
recvlength > LBS_CMD_BUFFER_SIZE) {
lbs_deb_usbd(&cardp->udev->dev,
"The receive buffer is too large\n");
"The receive buffer is invalid: %d\n", recvlength);
kfree_skb(skb);
return;
}

View File

@ -70,12 +70,11 @@ static inline int rsi_create_kthread(struct rsi_common *common,
return 0;
}
static inline int rsi_kill_thread(struct rsi_thread *handle)
static inline void rsi_kill_thread(struct rsi_thread *handle)
{
atomic_inc(&handle->thread_done);
rsi_set_event(&handle->event);
return kthread_stop(handle->task);
wait_for_completion(&handle->completion);
}
void rsi_mac80211_detach(struct rsi_hw *hw);

View File

@ -264,14 +264,12 @@ int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan)
wiphy_err(priv->hw->wiphy,
"PM request failed: %d. WoW is disabled.\n", ret);
cw1200_wow_resume(hw);
mutex_unlock(&priv->conf_mutex);
return -EBUSY;
}
/* Force resume if event is coming from the device. */
if (atomic_read(&priv->bh_rx)) {
cw1200_wow_resume(hw);
mutex_unlock(&priv->conf_mutex);
return -EAGAIN;
}

View File

@ -437,6 +437,15 @@ ieee80211_verify_sta_ht_mcs_support(struct ieee80211_sub_if_data *sdata,
memcpy(&sta_ht_cap, &sband->ht_cap, sizeof(sta_ht_cap));
ieee80211_apply_htcap_overrides(sdata, &sta_ht_cap);
/*
* Some Xfinity XB8 firmware advertises >1 spatial stream MCS indexes in
* their basic HT-MCS set. On cards with lower spatial streams, the check
* would fail, and we'd be stuck with no HT when it in fact work fine with
* its own supported rate. So check it only in strict mode.
*/
if (!ieee80211_hw_check(&sdata->local->hw, STRICT))
return true;
/*
* P802.11REVme/D7.0 - 6.5.4.2.4
* ...
@ -9140,7 +9149,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
struct ieee80211_bss *bss = (void *)cbss->priv;
struct sta_info *new_sta = NULL;
struct ieee80211_link_data *link;
bool have_sta = false;
struct sta_info *have_sta = NULL;
bool mlo;
int err;
u16 new_links;
@ -9159,11 +9168,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
mlo = false;
}
if (assoc) {
rcu_read_lock();
if (assoc)
have_sta = sta_info_get(sdata, ap_mld_addr);
rcu_read_unlock();
}
if (mlo && !have_sta &&
WARN_ON(sdata->vif.valid_links || sdata->vif.active_links))
@ -9327,6 +9333,8 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
out_release_chan:
ieee80211_link_release_channel(link);
out_err:
if (mlo && have_sta)
WARN_ON(__sta_info_destroy(have_sta));
ieee80211_vif_set_links(sdata, 0, 0);
return err;
}

View File

@ -4971,7 +4971,7 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
struct sk_buff *skb = rx->skb;
struct ieee80211_hdr *hdr = (void *)skb->data;
struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
static ieee80211_rx_result res;
ieee80211_rx_result res;
int orig_len = skb->len;
int hdrlen = ieee80211_hdrlen(hdr->frame_control);
int snap_offs = hdrlen;
@ -5380,7 +5380,9 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
if (!link_sta)
goto out;
ieee80211_rx_data_set_link(&rx, link_sta->link_id);
if (!ieee80211_rx_data_set_link(&rx,
link_sta->link_id))
goto out;
}
if (ieee80211_prepare_and_rx_handle(&rx, skb, true))

View File

@ -65,6 +65,7 @@ static const struct determine_chan_mode_case {
.ht_capa_mask = {
.mcs.rx_mask[0] = 0xf7,
},
.strict = true,
}, {
.desc = "Masking out a RX rate in VHT capabilities",
.conn_mode = IEEE80211_CONN_MODE_EHT,

View File

@ -3700,11 +3700,11 @@ void ieee80211_dfs_radar_detected_work(struct wiphy *wiphy,
struct ieee80211_local *local =
container_of(work, struct ieee80211_local, radar_detected_work);
struct cfg80211_chan_def chandef;
struct ieee80211_chanctx *ctx;
struct ieee80211_chanctx *ctx, *tmp;
lockdep_assert_wiphy(local->hw.wiphy);
list_for_each_entry(ctx, &local->chanctx_list, list) {
list_for_each_entry_safe(ctx, tmp, &local->chanctx_list, list) {
if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
continue;

View File

@ -1276,6 +1276,18 @@ static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
rtnl_unlock();
return -ENODEV;
}
/*
* The first invocation validated the wdev's netns against
* the caller via __cfg80211_wdev_from_attrs(). The wiphy
* may have moved netns between dumpit invocations (via
* NL80211_CMD_SET_WIPHY_NETNS), so re-check here.
*/
if (!net_eq(wiphy_net(wiphy), sock_net(cb->skb->sk))) {
rtnl_unlock();
return -ENODEV;
}
*rdev = wiphy_to_rdev(wiphy);
*wdev = NULL;
@ -13867,6 +13879,19 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
if (IS_ERR(net))
return PTR_ERR(net);
/*
* The caller already has CAP_NET_ADMIN over the source netns
* (enforced by GENL_UNS_ADMIN_PERM on the genl op). Mirror the
* convention used by net/core/rtnetlink.c::rtnl_get_net_ns_capable()
* and require CAP_NET_ADMIN over the target netns as well, so that
* a caller that is privileged in their own user namespace cannot
* push a wiphy into a netns where they have no privilege.
*/
if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) {
put_net(net);
return -EPERM;
}
err = 0;
/* check if anything to do */
@ -19828,6 +19853,7 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.cmd = NL80211_CMD_SET_PMK,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_set_pmk,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_CLEAR_SKB),
},
@ -19835,6 +19861,7 @@ static const struct genl_small_ops nl80211_small_ops[] = {
.cmd = NL80211_CMD_DEL_PMK,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = nl80211_del_pmk,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = IFLAGS(NL80211_FLAG_NEED_NETDEV_UP),
},
{

View File

@ -88,7 +88,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev,
out->ftm.ftms_per_burst = 0;
if (tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST])
out->ftm.ftms_per_burst =
nla_get_u32(tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST]);
nla_get_u8(tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST]);
if (capa->ftm.max_ftms_per_burst &&
(out->ftm.ftms_per_burst > capa->ftm.max_ftms_per_burst ||