> Date: Sun, 31 Jan 2016 13:36:17 +0100 > From: Stefan Sperling <s...@stsp.name> > > On Sun, Jan 31, 2016 at 12:53:09PM +0100, Stefan Sperling wrote: > > This matters for frames which arrived in A-MPDUs. > > > > Before: > > > > 12:35:07.726898 802.11: QoS data: 00:1e:52:f1:80:55 sap 00 > > > 58:94:6b:06:70:04 sap 06 I (s=85,r=85,C) len=82 > > > > After: > > > > 12:49:08.879003 802.11: QoS data: 10.197.84.33 > 10.0.1.3: icmp: echo reply > > Missed another case further down.
I think you should add a TCHECK somewhere at the top for the qos frame size otherwise this might look beyond the end of the buffer for specially crafted frames. > Index: print-802_11.c > =================================================================== > RCS file: /cvs/src/usr.sbin/tcpdump/print-802_11.c,v > retrieving revision 1.28 > diff -u -p -r1.28 print-802_11.c > --- print-802_11.c 12 Jan 2016 09:28:10 -0000 1.28 > +++ print-802_11.c 31 Jan 2016 12:19:55 -0000 > @@ -153,14 +153,21 @@ int > ieee80211_data(struct ieee80211_frame *wh, u_int len) > { > u_int8_t *t = (u_int8_t *)wh; > - struct ieee80211_frame_addr4 *w4; > u_int datalen; > int data = !(wh->i_fc[0] & IEEE80211_FC0_SUBTYPE_NODATA); > + int hasqos = ((wh->i_fc[0] & > + (IEEE80211_FC0_TYPE_MASK | IEEE80211_FC0_SUBTYPE_QOS)) == > + (IEEE80211_FC0_TYPE_DATA | IEEE80211_FC0_SUBTYPE_QOS)); > u_char *esrc = NULL, *edst = NULL; > > TCHECK(*wh); > - t += sizeof(struct ieee80211_frame); > - datalen = len - sizeof(struct ieee80211_frame); > + if (hasqos) { > + t += sizeof(struct ieee80211_qosframe); > + datalen = len - sizeof(struct ieee80211_qosframe); > + } else { > + t += sizeof(struct ieee80211_frame); > + datalen = len - sizeof(struct ieee80211_frame); > + } > > switch (wh->i_fc[1] & IEEE80211_FC1_DIR_MASK) { > case IEEE80211_FC1_DIR_TODS: > @@ -176,12 +183,25 @@ ieee80211_data(struct ieee80211_frame *w > edst = wh->i_addr1; > break; > case IEEE80211_FC1_DIR_DSTODS: > - w4 = (struct ieee80211_frame_addr4 *) wh; > - TCHECK(*w4); > - t = (u_int8_t *) (w4 + 1); > - datalen = len - sizeof(*w4); > - esrc = w4->i_addr4; > - edst = w4->i_addr3; > + if (hasqos) { > + struct ieee80211_qosframe_addr4 *w4; > + > + w4 = (struct ieee80211_qosframe_addr4 *) wh; > + TCHECK(*w4); > + t = (u_int8_t *) (w4 + 1); > + datalen = len - sizeof(*w4); > + esrc = w4->i_addr4; > + edst = w4->i_addr3; > + } else { > + struct ieee80211_frame_addr4 *w4; > + > + w4 = (struct ieee80211_frame_addr4 *) wh; > + TCHECK(*w4); > + t = (u_int8_t *) (w4 + 1); > + datalen = len - sizeof(*w4); > + esrc = w4->i_addr4; > + edst = w4->i_addr3; > + } > break; > } > > >