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().

MFC after:	3 days
Reviewed by:	adrian, cc
Differential Revision: https://reviews.freebsd.org/D43469
This commit is contained in:
Bjoern A. Zeeb 2024-01-16 18:53:06 +00:00
parent 2d9d35837d
commit 8a5a3e3d04

View file

@ -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 */
}