Date: Mon, 5 May 2025 14:59:10 GMT From: "Bjoern A. Zeeb" <bz@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: aff56b4f0b25 - main - net80211: fix a race between ieee80211_sta_join and scan entries Message-ID: <202505051459.545ExAeW021088@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=aff56b4f0b25c44c9c2cae9a3f816c4277057a71 commit aff56b4f0b25c44c9c2cae9a3f816c4277057a71 Author: Bjoern A. Zeeb <bz@FreeBSD.org> AuthorDate: 2025-04-16 19:10:58 +0000 Commit: Bjoern A. Zeeb <bz@FreeBSD.org> CommitDate: 2025-05-05 14:58:59 +0000 net80211: fix a race between ieee80211_sta_join and scan entries We were seeing panics during ieee80211_sta_join() which seemed that the ni->ni_chan was not valid anymore, which was true. We also saw errors indicating data put into ni_ies became inalid. The problem was that the ieee80211_scan_entry passed into ieee80211_sta_join() (in the observed case from setmlme_assoc_sta()) became invalid during ieee80211_alloc_node(). As a result for the ni_chan case the the rateset and len in rates[1] became invalid. Similarly for the IEs. Make a (deep)copy of the scan entry in setmlme_assoc_sta() and return the copy as once we leave ieee80211_scan_iterate() we can no longer rely on the scan entry to be valid. Sponsored by: The FreeBSD Foundation MFC after: 3 days Reported by: rm, ziaee, bz Tested by: rm, ziaee, bz PR: 286063 Reviewed by: adrian (,emaste) Differential Revision: https://reviews.freebsd.org/D49865 --- sys/net80211/ieee80211_ioctl.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c index caa0c77e2897..6c30325e5e32 100644 --- a/sys/net80211/ieee80211_ioctl.c +++ b/sys/net80211/ieee80211_ioctl.c @@ -1530,7 +1530,8 @@ struct scanlookup { const uint8_t *mac; int esslen; const uint8_t *essid; - const struct ieee80211_scan_entry *se; + bool found; + struct ieee80211_scan_entry se; }; /* @@ -1540,6 +1541,10 @@ static void mlmelookup(void *arg, const struct ieee80211_scan_entry *se) { struct scanlookup *look = arg; + int rv; + + if (look->found) + return; if (!IEEE80211_ADDR_EQ(look->mac, se->se_macaddr)) return; @@ -1549,7 +1554,14 @@ mlmelookup(void *arg, const struct ieee80211_scan_entry *se) if (memcmp(look->essid, se->se_ssid+2, look->esslen)) return; } - look->se = se; + /* + * First copy everything and then ensure we get our own copy of se_ies. */ + look->se = *se; + look->se.se_ies.data = 0; + look->se.se_ies.len = 0; + rv = ieee80211_ies_init(&look->se.se_ies, se->se_ies.data, se->se_ies.len); + if (rv != 0) /* No error */ + look->found = true; } static int @@ -1558,21 +1570,25 @@ setmlme_assoc_sta(struct ieee80211vap *vap, const uint8_t ssid[IEEE80211_NWID_LEN]) { struct scanlookup lookup; + int rv; KASSERT(vap->iv_opmode == IEEE80211_M_STA, ("expected opmode STA not %s", ieee80211_opmode_name[vap->iv_opmode])); /* NB: this is racey if roaming is !manual */ - lookup.se = NULL; lookup.mac = mac; lookup.esslen = ssid_len; lookup.essid = ssid; + memset(&lookup.se, 0, sizeof(lookup.se)); + lookup.found = false; ieee80211_scan_iterate(vap, mlmelookup, &lookup); - if (lookup.se == NULL) + if (!lookup.found) return ENOENT; mlmedebug(vap, mac, IEEE80211_MLME_ASSOC, 0); - if (!ieee80211_sta_join(vap, lookup.se->se_chan, lookup.se)) + rv = ieee80211_sta_join(vap, lookup.se.se_chan, &lookup.se); + ieee80211_ies_cleanup(&lookup.se.se_ies); + if (rv == 0) return EIO; /* XXX unique but could be better */ return 0; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202505051459.545ExAeW021088>