summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>2025-03-06 13:37:59 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-02-06 18:42:06 +0300
commit8930a3e1568cf534f86c8ed2def817c6d0528fc1 (patch)
tree64e3cfa8c94ce4aa9c59b5540e04561f0492899c
parentd81ebee178731e9f604d76a0c13770bcdf2417c7 (diff)
downloadlinux-8930a3e1568cf534f86c8ed2def817c6d0528fc1.tar.xz
wifi: cfg80211: cancel wiphy_work before freeing wiphy
commit 72d520476a2fab6f3489e8388ab524985d6c4b90 upstream. A wiphy_work can be queued from the moment the wiphy is allocated and initialized (i.e. wiphy_new_nm). When a wiphy_work is queued, the rdev::wiphy_work is getting queued. If wiphy_free is called before the rdev::wiphy_work had a chance to run, the wiphy memory will be freed, and then when it eventally gets to run it'll use invalid memory. Fix this by canceling the work before freeing the wiphy. Fixes: a3ee4dc84c4e ("wifi: cfg80211: add a work abstraction with special semantics") Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Reviewed-by: Johannes Berg <johannes.berg@intel.com> Link: https://patch.msgid.link/20250306123626.efd1d19f6e07.I48229f96f4067ef73f5b87302335e2fd750136c9@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/wireless/core.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index ca1c9b1ba344..e91ed429c5a6 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1127,6 +1127,13 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
{
struct cfg80211_internal_bss *scan, *tmp;
struct cfg80211_beacon_registration *reg, *treg;
+ unsigned long flags;
+
+ spin_lock_irqsave(&rdev->wiphy_work_lock, flags);
+ WARN_ON(!list_empty(&rdev->wiphy_work_list));
+ spin_unlock_irqrestore(&rdev->wiphy_work_lock, flags);
+ cancel_work_sync(&rdev->wiphy_work);
+
rfkill_destroy(rdev->wiphy.rfkill);
list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
list_del(&reg->list);