On Wed, Feb 03, 2016 at 05:25:55PM +0100, Mark Kettenis wrote:
> > Date: Wed, 3 Feb 2016 17:03:46 +0100
> > From: Stefan Sperling <[email protected]>
> >
> > This allows tcpdump to see all control frames with iwn(4).
>
> Hmm, the code below that does look inside the frame. How do we
> guarantee it isn't looking at garbage or reading beyond the end of the
> buffer?
Eeek, quite right. How about this?
Index: if_iwn.c
===================================================================
RCS file: /cvs/src/sys/dev/pci/if_iwn.c,v
retrieving revision 1.158
diff -u -p -r1.158 if_iwn.c
--- if_iwn.c 25 Jan 2016 11:27:11 -0000 1.158
+++ if_iwn.c 3 Feb 2016 17:44:43 -0000
@@ -2008,7 +2008,15 @@ iwn_rx_done(struct iwn_softc *sc, struct
return;
}
/* Discard frames that are too short. */
- if (len < sizeof (*wh)) {
+ if (ic->ic_opmode == IEEE80211_M_MONITOR) {
+ /* Allow control frames in monitor mode. */
+ if (len < sizeof (struct ieee80211_frame_cts)) {
+ DPRINTF(("frame too short: %d\n", len));
+ ic->ic_stats.is_rx_tooshort++;
+ ifp->if_ierrors++;
+ return;
+ }
+ } else if (len < sizeof (*wh)) {
DPRINTF(("frame too short: %d\n", len));
ic->ic_stats.is_rx_tooshort++;
ifp->if_ierrors++;
@@ -2058,12 +2066,24 @@ iwn_rx_done(struct iwn_softc *sc, struct
m->m_data = head;
m->m_pkthdr.len = m->m_len = len;
- /* Grab a reference to the source node. */
+ /*
+ * Grab a reference to the source node. Note that control frames are
+ * shorter than struct ieee80211_frame but ieee80211_find_rxnode()
+ * is being careful about control frames.
+ */
wh = mtod(m, struct ieee80211_frame *);
+ if (len < sizeof (*wh) &&
+ (wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL) {
+ ic->ic_stats.is_rx_tooshort++;
+ ifp->if_ierrors++;
+ m_freem(m);
+ return;
+ }
ni = ieee80211_find_rxnode(ic, wh);
rxi.rxi_flags = 0;
- if ((wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
+ if (((wh->i_fc[0] & IEEE80211_FC0_TYPE_MASK) != IEEE80211_FC0_TYPE_CTL)
+ && (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) &&
!IEEE80211_IS_MULTICAST(wh->i_addr1) &&
(ni->ni_flags & IEEE80211_NODE_RXPROT) &&
ni->ni_pairwise_key.k_cipher == IEEE80211_CIPHER_CCMP) {