diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c --- a/sys/net80211/ieee80211_sta.c +++ b/sys/net80211/ieee80211_sta.c @@ -552,6 +552,35 @@ int is_hw_decrypted = 0; int has_decrypted = 0; + KASSERT(ni != NULL, ("%s: null node, mbuf %p", __func__, m)); + + /* Early init in case of early error case. */ + type = -1; + + /* + * Bit of a cheat here, we use a pointer for a 3-address + * frame format but don't reference fields past outside + * ieee80211_frame_min (or other shorter frames) w/o first + * validating the data is present. + */ + wh = mtod(m, struct ieee80211_frame *); + + if (m->m_pkthdr.len < 2 || m->m_pkthdr.len < ieee80211_anyhdrsize(wh)) { + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, + ni->ni_macaddr, NULL, + "too short (1): len %u", m->m_pkthdr.len); + vap->iv_stats.is_rx_tooshort++; + goto err; + } + if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != + IEEE80211_FC0_VERSION_0) { + IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, + ni->ni_macaddr, NULL, "wrong version, fc %02x:%02x", + wh->i_fc[0], wh->i_fc[1]); + vap->iv_stats.is_rx_badversion++; + goto err; + } + /* * Some devices do hardware decryption all the way through * to pretending the frame wasn't encrypted in the first place. @@ -569,7 +598,6 @@ * with the M_AMPDU_MPDU flag and we can bypass most of * the normal processing. */ - wh = mtod(m, struct ieee80211_frame *); type = IEEE80211_FC0_TYPE_DATA; dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; subtype = IEEE80211_FC0_SUBTYPE_QOS; @@ -577,39 +605,19 @@ goto resubmit_ampdu; } - KASSERT(ni != NULL, ("null node")); ni->ni_inact = ni->ni_inact_reload; - type = -1; /* undefined */ - - if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) { - IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, - ni->ni_macaddr, NULL, - "too short (1): len %u", m->m_pkthdr.len); - vap->iv_stats.is_rx_tooshort++; - goto out; - } - /* - * Bit of a cheat here, we use a pointer for a 3-address - * frame format but don't reference fields past outside - * ieee80211_frame_min w/o first validating the data is - * present. - */ - wh = mtod(m, struct ieee80211_frame *); - - if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != - IEEE80211_FC0_VERSION_0) { - IEEE80211_DISCARD_MAC(vap, IEEE80211_MSG_ANY, - ni->ni_macaddr, NULL, "wrong version, fc %02x:%02x", - wh->i_fc[0], wh->i_fc[1]); - vap->iv_stats.is_rx_badversion++; - goto err; - } - dir = wh->i_fc[1] & IEEE80211_FC1_DIR_MASK; type = wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK; subtype = wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK; - if ((ic->ic_flags & IEEE80211_F_SCAN) == 0) { + /* + * Control frames are not folowing the header scheme of data and mgmt + * frames so we do not apply extra checks here. + * We probably should do checks on RA (+TA) where available for those + * too, but for now do not drop them. + */ + if (type != IEEE80211_FC0_TYPE_CTL && + (ic->ic_flags & IEEE80211_F_SCAN) == 0) { bssid = wh->i_addr2; if (!IEEE80211_ADDR_EQ(bssid, ni->ni_bssid)) { /* not interested in */