The branch stable/15 has been updated by bz:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=b0469fa7f10f9fe5510a5445f38d1bf0b832c1e7

commit b0469fa7f10f9fe5510a5445f38d1bf0b832c1e7
Author:     Bjoern A. Zeeb <b...@freebsd.org>
AuthorDate: 2025-09-11 14:44:10 +0000
Commit:     Bjoern A. Zeeb <b...@freebsd.org>
CommitDate: 2025-09-15 14:53:07 +0000

    LinuxKPI: 802.11: avoid recursive wiphy lock
    
    When freeing the last reference of the net80211 node the net80211
    node_free() code may directly call into the crypto code to delete
    the keys.  While we still holding the wiphy lock this would lead to
    a recursion on the non-recursive wiphy lock.  Defer freeing the
    reference until we are back under the net80211 com lock.
    
    Reported by:    Mark Phillips (mark freebsdfoundation.org) on 15.0-ALPHA1
    
    (cherry picked from commit 3c38dce87ecd2c87744e4b7ff1904ee841f88a47)
---
 sys/compat/linuxkpi/common/src/linux_80211.c | 54 ++++++++++++++++++----------
 1 file changed, 36 insertions(+), 18 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c 
b/sys/compat/linuxkpi/common/src/linux_80211.c
index d00734001a59..bc4b334de28e 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -2568,12 +2568,6 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum 
ieee80211_state nstate, int
        lvif->lvif_bss_synched = false;
        LKPI_80211_LVIF_UNLOCK(lvif);
        lkpi_lsta_remove(lsta, lvif);
-       /*
-        * The very last release the reference on the ni for the ni/lsta on
-        * lvif->lvif_bss.  Upon return from this both ni and lsta are invalid
-        * and potentially freed.
-        */
-       ieee80211_free_node(ni);
 
        /* conf_tx */
 
@@ -2582,6 +2576,18 @@ lkpi_sta_auth_to_scan(struct ieee80211vap *vap, enum 
ieee80211_state nstate, int
 out:
        wiphy_unlock(hw->wiphy);
        IEEE80211_LOCK(vap->iv_ic);
+       if (error == 0) {
+               /*
+                * We do this outside the wiphy lock as net80211::node_free() 
may call
+                * into crypto code to delete keys and we have a recursed on
+                * non-recursive sx panic.  Also only do this if we get here 
w/o error.
+                *
+                * The very last release the reference on the ni for the 
ni/lsta on
+                * lvif->lvif_bss.  Upon return from this both ni and lsta are 
invalid
+                * and potentially freed.
+                */
+               ieee80211_free_node(ni);
+       }
        return (error);
 }
 
@@ -2906,12 +2912,6 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum 
ieee80211_state nstate, i
        lvif->lvif_bss_synched = false;
        LKPI_80211_LVIF_UNLOCK(lvif);
        lkpi_lsta_remove(lsta, lvif);
-       /*
-        * The very last release the reference on the ni for the ni/lsta on
-        * lvif->lvif_bss.  Upon return from this both ni and lsta are invalid
-        * and potentially freed.
-        */
-       ieee80211_free_node(ni);
 
        /* conf_tx */
 
@@ -2921,6 +2921,18 @@ _lkpi_sta_assoc_to_down(struct ieee80211vap *vap, enum 
ieee80211_state nstate, i
 out:
        wiphy_unlock(hw->wiphy);
        IEEE80211_LOCK(vap->iv_ic);
+       if (error == EALREADY) {
+               /*
+                * We do this outside the wiphy lock as net80211::node_free() 
may call
+                * into crypto code to delete keys and we have a recursed on
+                * non-recursive sx panic.  Also only do this if we get here 
w/o error.
+                *
+                * The very last release the reference on the ni for the 
ni/lsta on
+                * lvif->lvif_bss.  Upon return from this both ni and lsta are 
invalid
+                * and potentially freed.
+                */
+               ieee80211_free_node(ni);
+       }
 outni:
        return (error);
 }
@@ -3522,12 +3534,6 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum 
ieee80211_state nstate, int
        lvif->lvif_bss = NULL;
        lvif->lvif_bss_synched = false;
        LKPI_80211_LVIF_UNLOCK(lvif);
-       /*
-        * The very last release the reference on the ni for the ni/lsta on
-        * lvif->lvif_bss.  Upon return from this both ni and lsta are invalid
-        * and potentially freed.
-        */
-       ieee80211_free_node(ni);
 
        /* conf_tx */
 
@@ -3537,6 +3543,18 @@ lkpi_sta_run_to_init(struct ieee80211vap *vap, enum 
ieee80211_state nstate, int
 out:
        wiphy_unlock(hw->wiphy);
        IEEE80211_LOCK(vap->iv_ic);
+       if (error == EALREADY) {
+               /*
+                * We do this outside the wiphy lock as net80211::node_free() 
may call
+                * into crypto code to delete keys and we have a recursed on
+                * non-recursive sx panic.  Also only do this if we get here 
w/o error.
+                *
+                * The very last release the reference on the ni for the 
ni/lsta on
+                * lvif->lvif_bss.  Upon return from this both ni and lsta are 
invalid
+                * and potentially freed.
+                */
+               ieee80211_free_node(ni);
+       }
 outni:
        return (error);
 }

Reply via email to