Commit 3dc7a189 authored by Bjoern A. Zeeb's avatar Bjoern A. Zeeb
Browse files

net80211: correct input_sta length checks and control frame handling

Correct input_sta "assertion" checks.  CTS/ACK CTRL frames are shorter
then sizeof(struct ieee80211_frame_min) and were thus running into the
is_rx_tooshort error case.
Use ieee80211_anyhdrsize() to handle this better but make sure we do
at least have the first 2 octets needed for that.
While here move the safety checks before any code which may not obey
them later, just for good style.

The non-scanning check further down assumes a frame format also not
matching control frames.  For now skip the checks for control frames
which allows us to deal with some of them at least now.

Sponsored by:	The FreeBSD Foundation
Obtained from:	20210906 wireless v0.91 code drop
MFC after:	3 days
Reviewed by:	adrian
Differential Revision: https://reviews.freebsd.org/D32238
parent 9a669553
......@@ -552,6 +552,35 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
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 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
* 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 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
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 */
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment