aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMathy Vanhoef <Mathy.Vanhoef@kuleuven.be>2021-06-06 22:10:52 +0000
committerMark Johnston <markj@FreeBSD.org>2022-03-15 17:47:01 +0000
commit5616c3920f8a6a5792f23c1975780f4b54888aa1 (patch)
tree007e95871c405329ca6b40227e58d0a68f63f581 /sys
parentf0df8a13116dca6ac42334d23430160fbeaf6c09 (diff)
Diffstat (limited to 'sys')
-rw-r--r--sys/net80211/ieee80211_adhoc.c2
-rw-r--r--sys/net80211/ieee80211_hostap.c2
-rw-r--r--sys/net80211/ieee80211_input.c20
-rw-r--r--sys/net80211/ieee80211_input.h3
-rw-r--r--sys/net80211/ieee80211_sta.c2
-rw-r--r--sys/net80211/ieee80211_wds.c2
6 files changed, 24 insertions, 7 deletions
diff --git a/sys/net80211/ieee80211_adhoc.c b/sys/net80211/ieee80211_adhoc.c
index ea1519b3381d..c97b99425caa 100644
--- a/sys/net80211/ieee80211_adhoc.c
+++ b/sys/net80211/ieee80211_adhoc.c
@@ -558,7 +558,7 @@ adhoc_input(struct ieee80211_node *ni, struct mbuf *m,
/*
* Finally, strip the 802.11 header.
*/
- m = ieee80211_decap(vap, m, hdrspace);
+ m = ieee80211_decap(vap, m, hdrspace, qos);
if (m == NULL) {
/* XXX mask bit to check for both */
/* don't count Null data frames as errors */
diff --git a/sys/net80211/ieee80211_hostap.c b/sys/net80211/ieee80211_hostap.c
index 6687276d0181..8c132332f86b 100644
--- a/sys/net80211/ieee80211_hostap.c
+++ b/sys/net80211/ieee80211_hostap.c
@@ -744,7 +744,7 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m,
/*
* Finally, strip the 802.11 header.
*/
- m = ieee80211_decap(vap, m, hdrspace);
+ m = ieee80211_decap(vap, m, hdrspace, qos);
if (m == NULL) {
/* XXX mask bit to check for both */
/* don't count Null data frames as errors */
diff --git a/sys/net80211/ieee80211_input.c b/sys/net80211/ieee80211_input.c
index 404eaf96716a..979e9aef9d12 100644
--- a/sys/net80211/ieee80211_input.c
+++ b/sys/net80211/ieee80211_input.c
@@ -294,7 +294,8 @@ ieee80211_deliver_data(struct ieee80211vap *vap,
}
struct mbuf *
-ieee80211_decap(struct ieee80211vap *vap, struct mbuf *m, int hdrlen)
+ieee80211_decap(struct ieee80211vap *vap, struct mbuf *m, int hdrlen,
+ uint8_t qos)
{
struct ieee80211_qosframe_addr4 wh;
struct ether_header *eh;
@@ -316,7 +317,9 @@ ieee80211_decap(struct ieee80211vap *vap, struct mbuf *m, int hdrlen)
llc->llc_snap.org_code[1] == 0 && llc->llc_snap.org_code[2] == 0 &&
/* NB: preserve AppleTalk frames that have a native SNAP hdr */
!(llc->llc_snap.ether_type == htons(ETHERTYPE_AARP) ||
- llc->llc_snap.ether_type == htons(ETHERTYPE_IPX))) {
+ llc->llc_snap.ether_type == htons(ETHERTYPE_IPX)) &&
+ /* Do not want to touch A-MSDU frames. */
+ !(qos & IEEE80211_QOS_AMSDU)) {
m_adj(m, hdrlen + sizeof(struct llc) - sizeof(*eh));
llc = NULL;
} else {
@@ -364,6 +367,10 @@ ieee80211_decap1(struct mbuf *m, int *framelen)
#define FF_LLC_SIZE (sizeof(struct ether_header) + sizeof(struct llc))
struct ether_header *eh;
struct llc *llc;
+ const uint8_t llc_hdr_mac[ETHER_ADDR_LEN] = {
+ /* MAC address matching the 802.2 LLC header */
+ LLC_SNAP_LSAP, LLC_SNAP_LSAP, LLC_UI, 0, 0, 0
+ };
/*
* The frame has an 802.3 header followed by an 802.2
@@ -376,6 +383,15 @@ ieee80211_decap1(struct mbuf *m, int *framelen)
if (m->m_len < FF_LLC_SIZE && (m = m_pullup(m, FF_LLC_SIZE)) == NULL)
return NULL;
eh = mtod(m, struct ether_header *); /* 802.3 header is first */
+
+ /*
+ * Detect possible attack where a single 802.11 frame is processed
+ * as an A-MSDU frame due to an adversary setting the A-MSDU present
+ * bit in the 802.11 QoS header. [FragAttacks]
+ */
+ if (memcmp(eh->ether_dhost, llc_hdr_mac, ETHER_ADDR_LEN) == 0)
+ return NULL;
+
llc = (struct llc *)&eh[1]; /* 802.2 header follows */
*framelen = ntohs(eh->ether_type) /* encap'd frame size */
+ sizeof(struct ether_header) - sizeof(struct llc);
diff --git a/sys/net80211/ieee80211_input.h b/sys/net80211/ieee80211_input.h
index 810dcbde7978..5959319c76d7 100644
--- a/sys/net80211/ieee80211_input.h
+++ b/sys/net80211/ieee80211_input.h
@@ -311,7 +311,8 @@ void ieee80211_deliver_data(struct ieee80211vap *,
struct mbuf *ieee80211_defrag(struct ieee80211_node *,
struct mbuf *, int);
struct mbuf *ieee80211_realign(struct ieee80211vap *, struct mbuf *, size_t);
-struct mbuf *ieee80211_decap(struct ieee80211vap *, struct mbuf *, int);
+struct mbuf *ieee80211_decap(struct ieee80211vap *, struct mbuf *, int,
+ uint8_t);
struct mbuf *ieee80211_decap1(struct mbuf *, int *);
int ieee80211_setup_rates(struct ieee80211_node *ni,
const uint8_t *rates, const uint8_t *xrates, int flags);
diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c
index 75f6c652c0fb..56372543a200 100644
--- a/sys/net80211/ieee80211_sta.c
+++ b/sys/net80211/ieee80211_sta.c
@@ -827,7 +827,7 @@ sta_input(struct ieee80211_node *ni, struct mbuf *m,
/*
* Finally, strip the 802.11 header.
*/
- m = ieee80211_decap(vap, m, hdrspace);
+ m = ieee80211_decap(vap, m, hdrspace, qos);
if (m == NULL) {
/* XXX mask bit to check for both */
/* don't count Null data frames as errors */
diff --git a/sys/net80211/ieee80211_wds.c b/sys/net80211/ieee80211_wds.c
index ea13572cf2d9..74cc764b856e 100644
--- a/sys/net80211/ieee80211_wds.c
+++ b/sys/net80211/ieee80211_wds.c
@@ -619,7 +619,7 @@ wds_input(struct ieee80211_node *ni, struct mbuf *m,
/*
* Finally, strip the 802.11 header.
*/
- m = ieee80211_decap(vap, m, hdrspace);
+ m = ieee80211_decap(vap, m, hdrspace, qos);
if (m == NULL) {
/* XXX mask bit to check for both */
/* don't count Null data frames as errors */