diff options
author | Damien Bergamini <damien@cvs.openbsd.org> | 2009-05-19 16:09:03 +0000 |
---|---|---|
committer | Damien Bergamini <damien@cvs.openbsd.org> | 2009-05-19 16:09:03 +0000 |
commit | bb426317f9472082d5f6b2ffb02058cd1a8c3db1 (patch) | |
tree | c838b2a93e7faa8364aee113c7f092b750dd6eab | |
parent | fa7f6a6696d4c8d62bdbd2124e22e9b03416611b (diff) |
prevent injection of raw 802.11 control frames through bpf on drivers
that do not explicitly state this capability (using flag IEEE80211_C_RAWCTL).
also, perform all the sanity checks on injected raw 802.11 frames earlier
(in ieee80211_output instead of ieee80211_encap).
prevent kernel panics with many drivers when running aircrack-ng.
when/if all drivers are capable, we can remove this C_RAWCTL flag.
-rw-r--r-- | sys/net80211/ieee80211_output.c | 23 | ||||
-rw-r--r-- | sys/net80211/ieee80211_var.h | 3 |
2 files changed, 16 insertions, 10 deletions
diff --git a/sys/net80211/ieee80211_output.c b/sys/net80211/ieee80211_output.c index f4a2911220f..9c64a5545bd 100644 --- a/sys/net80211/ieee80211_output.c +++ b/sys/net80211/ieee80211_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_output.c,v 1.85 2009/03/26 20:34:54 damien Exp $ */ +/* $OpenBSD: ieee80211_output.c,v 1.86 2009/05/19 16:09:02 damien Exp $ */ /* $NetBSD: ieee80211_output.c,v 1.13 2004/05/31 11:02:55 dyoung Exp $ */ /*- @@ -116,6 +116,7 @@ int ieee80211_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rt) { + struct ieee80211_frame *wh; struct m_tag *mtag; int s, len, error = 0; u_short mflags; @@ -129,12 +130,24 @@ ieee80211_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, /* Try to get the DLT from a mbuf tag */ if ((mtag = m_tag_find(m, PACKET_TAG_DLT, NULL)) != NULL) { + struct ieee80211com *ic = (void *)ifp; u_int dlt = *(u_int *)(mtag + 1); /* Fallback to ethernet for non-802.11 linktypes */ if (!(dlt == DLT_IEEE802_11 || dlt == DLT_IEEE802_11_RADIO)) goto fallback; + if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) + return (EINVAL); + wh = mtod(m, struct ieee80211_frame *); + if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != + IEEE80211_FC0_VERSION_0) + return (EINVAL); + if (!(ic->ic_flags & IEEE80211_C_RAWCTL) && + (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) == + IEEE80211_FC0_TYPE_CTL) + return (EINVAL); + /* * Queue message on interface without adding any * further headers, and start output if interface not @@ -495,14 +508,6 @@ ieee80211_encap(struct ifnet *ifp, struct mbuf *m, struct ieee80211_node **pni) goto fallback; wh = mtod(m, struct ieee80211_frame *); - - if (m->m_pkthdr.len < sizeof(struct ieee80211_frame_min)) - goto bad; - - if ((wh->i_fc[0] & IEEE80211_FC0_VERSION_MASK) != - IEEE80211_FC0_VERSION_0) - goto bad; - switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { case IEEE80211_FC1_DIR_NODS: case IEEE80211_FC1_DIR_FROMDS: diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h index beb8d0f77d9..e5154e15705 100644 --- a/sys/net80211/ieee80211_var.h +++ b/sys/net80211/ieee80211_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_var.h,v 1.59 2009/03/26 20:38:29 damien Exp $ */ +/* $OpenBSD: ieee80211_var.h,v 1.60 2009/05/19 16:09:02 damien Exp $ */ /* $NetBSD: ieee80211_var.h,v 1.7 2004/05/06 03:07:10 dyoung Exp $ */ /*- @@ -365,6 +365,7 @@ extern struct ieee80211com_head ieee80211com_head; #define IEEE80211_C_QOS 0x00000800 /* CAPABILITY: QoS avail */ #define IEEE80211_C_RSN 0x00001000 /* CAPABILITY: RSN avail */ #define IEEE80211_C_MFP 0x00002000 /* CAPABILITY: MFP avail */ +#define IEEE80211_C_RAWCTL 0x00004000 /* CAPABILITY: raw ctl */ /* flags for ieee80211_fix_rate() */ #define IEEE80211_F_DOSORT 0x00000001 /* sort rate list */ |