]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: mac80211: avoid double free in auth/assoc timeout
authorMiri Korenblit <miriam.rachel.korenblit@intel.com>
Thu, 2 Jan 2025 14:20:09 +0000 (16:20 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 13 Jan 2025 14:34:10 +0000 (15:34 +0100)
In case of authentication/association timeout (as detected in
ieee80211_iface_work->ieee80211_sta_work), ieee80211_destroy_auth_data
is called.
At the beginning of it, the pointer to ifmgd::auth_data memory is
copied to a local variable.
If iface_work is queued again during the execution of the current one,
and then the driver is flushing the wiphy_works (for its needs),
ieee80211_destroy_auth_data will run again and free auth_data.
Then when the execution of the original worker continues, the previously
copied pointer will be freed, causing a kernel bug:
 kernel BUG at mm/slub.c:553! (double free)

Same for association timeout (just with ieee80211_destroy_assoc_data and
ifmgd::assoc_data)

Fix this by NULLifying auth/assoc data right after we copied
the pointer to it. That way, even in the scenario above, the code will
not handle the same timeout twice.

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Link: https://patch.msgid.link/20250102161730.0c3f7f781096.I2b458fb53291b06717077a815755288a81274756@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/mlme.c

index 9bc0db308a969ebd46fffa7419220bc4b9d70358..0d3f64eb573e3dc02f9c3e7e1a426a9d0db59862 100644 (file)
@@ -4402,6 +4402,8 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
 
        lockdep_assert_wiphy(sdata->local->hw.wiphy);
 
+       sdata->u.mgd.auth_data = NULL;
+
        if (!assoc) {
                /*
                 * we are not authenticated yet, the only timer that could be
@@ -4423,7 +4425,6 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
 
        cfg80211_put_bss(sdata->local->hw.wiphy, auth_data->bss);
        kfree(auth_data);
-       sdata->u.mgd.auth_data = NULL;
 }
 
 enum assoc_status {
@@ -4440,6 +4441,8 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
 
        lockdep_assert_wiphy(sdata->local->hw.wiphy);
 
+       sdata->u.mgd.assoc_data = NULL;
+
        if (status != ASSOC_SUCCESS) {
                /*
                 * we are not associated yet, the only timer that could be
@@ -4478,7 +4481,6 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
        }
 
        kfree(assoc_data);
-       sdata->u.mgd.assoc_data = NULL;
 }
 
 static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,