DF-3363 / fix.diff
--- a/sys/netproto/802_11/wlan/ieee80211_scan_sta.c +++ b/sys/netproto/802_11/wlan/ieee80211_scan_sta.c @@ -394,15 +394,17 @@ if (rssi > st->st_maxrssi[sp->bchan]) st->st_maxrssi[sp->bchan] = rssi; - IEEE80211_SCAN_TABLE_UNLOCK(st); - /* * If looking for a quick choice and nothing's - * been found check here. + * been found check here. NB: keep the table lock + * across match_bss -- se must not be usable after + * a concurrent flush frees it. */ if (PICK1ST(ss) && match_bss(vap, ss, se, IEEE80211_MSG_SCAN) == 0) ss->ss_flags |= IEEE80211_SCAN_GOTPICK; + IEEE80211_SCAN_TABLE_UNLOCK(st); + return 1; #undef PICK1ST #undef ISPROBE @@ -779,6 +781,14 @@ uint8_t txparams; rmax = 0; + /* se_ies.htcap_ie comes from the verbatim-saved beacon blob; + * ieee80211_ies_expand() sets it for ANY HTCAP IE regardless of + * its declared length. Validate before dereferencing fields up + * to hc_mcsset[12] (offset 17), else a short (e.g. trailing) + * IE makes us read past the IE and past the heap allocation. */ + if (htcap != NULL && + htcap->hc_len < sizeof(struct ieee80211_ie_htcap) - 2) + htcap = NULL; if (htcap != NULL) { /* * HT station; inspect supported MCS and then adjust @@ -962,6 +972,10 @@ int slot, slotcnt; slotcnt = tdma->tdma_slotcnt; + /* tdma_inuse[] holds 8 slots per byte; clamp a bogus count so the + * bit scan cannot run past the IE (and past the allocation). */ + if (slotcnt > 8 * nitems(tdma->tdma_inuse)) + slotcnt = 8 * nitems(tdma->tdma_inuse); for (slot = slotcnt-1; slot >= 0; slot--) if (isclr(tdma->tdma_inuse, slot)) return 0; @@ -1020,6 +1034,13 @@ if (tdma == NULL) fail |= MATCH_TDMA_NOIE; + else if (tdma->tdma_len < + sizeof(struct ieee80211_tdma_param) - 2) + /* short IE: fields would read past the IE */ + fail |= MATCH_TDMA_NOIE; + else if (ts == NULL) + /* driver never attached TDMA state */ + fail |= MATCH_TDMA_NOIE; else if (tdma->tdma_version != ts->tdma_version) fail |= MATCH_TDMA_VERSION; else if (tdma->tdma_slot != 0) |