summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDamien Bergamini <damien@cvs.openbsd.org>2009-05-19 16:09:03 +0000
committerDamien Bergamini <damien@cvs.openbsd.org>2009-05-19 16:09:03 +0000
commitbb426317f9472082d5f6b2ffb02058cd1a8c3db1 (patch)
treec838b2a93e7faa8364aee113c7f092b750dd6eab
parentfa7f6a6696d4c8d62bdbd2124e22e9b03416611b (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.c23
-rw-r--r--sys/net80211/ieee80211_var.h3
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 */