git: a6413bce4e36 - main - LinuxKPI: 802.11: further improve key updates

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Wed, 23 Apr 2025 16:25:25 UTC
The branch main has been updated by bz:

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

commit a6413bce4e36e4176bbcf16528cc3aeb834965ba
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2025-04-16 21:11:03 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2025-04-23 16:24:21 +0000

    LinuxKPI: 802.11: further improve key updates
    
    Make sure the iv_bss noce does not go away in the middle of a key update
    given we unlocked.  Just as a precaution.  No real case has been seen
    so far.
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      3 days
    Fixes:          a6165709e3c8
---
 sys/compat/linuxkpi/common/src/linux_80211.c | 22 +++++++++++++++++++++-
 sys/compat/linuxkpi/common/src/linux_80211.h |  1 +
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_80211.c b/sys/compat/linuxkpi/common/src/linux_80211.c
index eef8024c5e84..6f9fda2e2234 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.c
+++ b/sys/compat/linuxkpi/common/src/linux_80211.c
@@ -1527,6 +1527,7 @@ lkpi_iv_key_update_begin(struct ieee80211vap *vap)
 	struct lkpi_hw *lhw;
 	struct ieee80211_hw *hw;
 	struct lkpi_vif *lvif;
+	struct ieee80211_node *ni;
 	bool icislocked, ntislocked;
 
 	ic = vap->iv_ic;
@@ -1547,7 +1548,16 @@ lkpi_iv_key_update_begin(struct ieee80211vap *vap)
 		    lvif->ic_unlocked, lvif->nt_unlocked);
 #endif
 
-	/* This is inconsistent net80211 locking to be fixed one day. */
+	/*
+	 * This is inconsistent net80211 locking to be fixed one day.
+	 */
+	/* Try to make sure the node does not go away while possibly unlocked. */
+	ni = NULL;
+	if (icislocked || ntislocked) {
+		if (vap->iv_bss != NULL)
+			ni = ieee80211_ref_node(vap->iv_bss);
+	}
+
 	if (icislocked)
 		IEEE80211_UNLOCK(ic);
 	if (ntislocked)
@@ -1555,6 +1565,10 @@ lkpi_iv_key_update_begin(struct ieee80211vap *vap)
 
 	wiphy_lock(hw->wiphy);
 
+	KASSERT(lvif->key_update_iv_bss == NULL, ("%s: key_update_iv_bss not NULL %p",
+	    __func__, lvif->key_update_iv_bss));
+	lvif->key_update_iv_bss = ni;
+
 	/*
 	 * ic/nt_unlocked could be a bool given we are under the lock and there
 	 * must only be a single thread.
@@ -1604,6 +1618,12 @@ lkpi_iv_key_update_end(struct ieee80211vap *vap)
 	 */
 	icislocked = refcount_release_if_last(&lvif->ic_unlocked);
 	ntislocked = refcount_release_if_last(&lvif->nt_unlocked);
+
+	if (lvif->key_update_iv_bss != NULL) {
+		ieee80211_free_node(lvif->key_update_iv_bss);
+		lvif->key_update_iv_bss = NULL;
+	}
+
 	wiphy_unlock(hw->wiphy);
 
 	/*
diff --git a/sys/compat/linuxkpi/common/src/linux_80211.h b/sys/compat/linuxkpi/common/src/linux_80211.h
index a5c052c78db0..89afec1235bd 100644
--- a/sys/compat/linuxkpi/common/src/linux_80211.h
+++ b/sys/compat/linuxkpi/common/src/linux_80211.h
@@ -191,6 +191,7 @@ struct lkpi_vif {
 
 	struct lkpi_sta		*lvif_bss;
 
+	struct ieee80211_node	*key_update_iv_bss;
 	int			ic_unlocked;			/* Count of ic unlocks pending (*mo_set_key) */
 	int			nt_unlocked;			/* Count of nt unlocks pending (*mo_set_key) */
 	bool			lvif_bss_synched;