git: f7c8d5448446 - releng/13.3 - net80211: fix a NULL deref in ieee80211_sta_join1()

From: Bjoern A. Zeeb <bz_at_FreeBSD.org>
Date: Mon, 19 Feb 2024 16:10:21 UTC
The branch releng/13.3 has been updated by bz:

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

commit f7c8d5448446a470baaca560f91c884e5ceeecc7
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-19 16:07:06 +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().
    
    Approved by:    re (cperciva)
    Reviewed by:    adrian, cc
    Differential Revision: https://reviews.freebsd.org/D43469
    
    (cherry picked from commit 8a5a3e3d0436a2de9dc5c2c10bd9a471b6338233)
    (cherry picked from commit 755a04671dd47390f6d49695a6ac9c2d31c9935c)
---
 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 a70edfa3acc4..0f0ecf37fe94 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 */
 	}