wifi: ath12k: fix node corruption in ar->arvifs list
authorMaharaja Kennadyrajan <maharaja.kennadyrajan@oss.qualcomm.com>
Wed, 16 Apr 2025 02:17:24 +0000 (07:47 +0530)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Thu, 17 Apr 2025 22:49:35 +0000 (15:49 -0700)
In current WLAN recovery code flow, ath12k_core_halt() only reinitializes
the "arvifs" list head. This will cause the list node immediately following
the list head to become an invalid list node. Because the prev of that node
still points to the list head "arvifs", but the next of the list head
"arvifs" no longer points to that list node.

When a WLAN recovery occurs during the execution of a vif removal, and it
happens before the spin_lock_bh(&ar->data_lock) in
ath12k_mac_vdev_delete(), list_del() will detect the previously mentioned
situation, thereby triggering a kernel panic.

The fix is to remove and reinitialize all vif list nodes from the list head
"arvifs" during WLAN halt. The reinitialization is to make the list nodes
valid, ensuring that the list_del() in ath12k_mac_vdev_delete() can execute
normally.

Call trace:
__list_del_entry_valid_or_report+0xd4/0x100 (P)
ath12k_mac_remove_link_interface.isra.0+0xf8/0x2e4 [ath12k]
ath12k_scan_vdev_clean_work+0x40/0x164 [ath12k]
cfg80211_wiphy_work+0xfc/0x100
process_one_work+0x164/0x2d0
worker_thread+0x254/0x380
kthread+0xfc/0x100
ret_from_fork+0x10/0x20

The change is mostly copied from the ath11k patch:
https://lore.kernel.org/all/20250320053145.3445187-1-quic_stonez@quicinc.com/

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1

Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Maharaja Kennadyrajan <maharaja.kennadyrajan@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20250416021724.2162519-1-maharaja.kennadyrajan@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/core.c

index b501d72..7eccd9c 100644 (file)
@@ -1371,6 +1371,7 @@ static void ath12k_rfkill_work(struct work_struct *work)
 
 void ath12k_core_halt(struct ath12k *ar)
 {
+       struct list_head *pos, *n;
        struct ath12k_base *ab = ar->ab;
 
        lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -1387,7 +1388,12 @@ void ath12k_core_halt(struct ath12k *ar)
 
        rcu_assign_pointer(ab->pdevs_active[ar->pdev_idx], NULL);
        synchronize_rcu();
-       INIT_LIST_HEAD(&ar->arvifs);
+
+       spin_lock_bh(&ar->data_lock);
+       list_for_each_safe(pos, n, &ar->arvifs)
+               list_del_init(pos);
+       spin_unlock_bh(&ar->data_lock);
+
        idr_init(&ar->txmgmt_idr);
 }