git: 680fd9feb104 - stable/14 - net80211: fix a NULL deref in ieee80211_sta_join1()

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Sun, 18 Feb 2024 21:11:27 UTC
The branch stable/14 has been updated by bz:

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

commit 680fd9feb10457525752841586c2d1c3bd740e23
Author:     Bjoern A. Zeeb <bz@FreeBSD.org>
AuthorDate: 2024-01-16 18:53:06 +0000
Commit:     Bjoern A. Zeeb <bz@FreeBSD.org>
CommitDate: 2024-02-18 18:31:16 +0000

    net80211: fix a NULL deref in ieee80211_sta_join1()
    
    When ieee80211_sta_join1() gets an obss without ni_nt trying to lock
    that will cause a NULL pointer deref.  Check for the table to be
    valid and deal with the obss node accordingly.
    
    This can happen if sta_newstate() calls ieee80211_reset_bss() for
    nstate == INIT and ostate != INIT.  ieee80211_reset_bss() itself
    calls ieee80211_node_table_reset() which calls node_reclaim()
    which ends up in ieee80211_del_node_nt() which does remove the
    node from the table and sets ni_table to NULL.
    That node (former iv_bss) can then be returned as obss in the
    (*iv_update_bss)() call in join1().
    
    Reviewed by:    adrian, cc
    Differential Revision: https://reviews.freebsd.org/D43469
    
    (cherry picked from commit 8a5a3e3d0436a2de9dc5c2c10bd9a471b6338233)
---
 sys/net80211/ieee80211_node.c | 13 ++++++++-----
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index 123da34ad3f1..f6bb4245f543 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -867,11 +867,14 @@ ieee80211_sta_join1(struct ieee80211_node *selbs)
 		struct ieee80211_node_table *nt = obss->ni_table;
 
 		copy_bss(selbs, obss);
-		ieee80211_node_decref(obss);	/* iv_bss reference */
-
-		IEEE80211_NODE_LOCK(nt);
-		node_reclaim(nt, obss);		/* station table reference */
-		IEEE80211_NODE_UNLOCK(nt);
+		if (nt != NULL) {
+			ieee80211_node_decref(obss);	/* iv_bss reference */
+			IEEE80211_NODE_LOCK(nt);
+			node_reclaim(nt, obss);		/* station table reference */
+			IEEE80211_NODE_UNLOCK(nt);
+		} else {
+			ieee80211_free_node(obss);	/* iv_bss reference */
+		}
 
 		obss = NULL;		/* NB: guard against later use */
 	}