diff -u b/epan/dissectors/packet-ieee80211-radiotap-iter.c b/epan/dissectors/packet-ieee80211-radiotap-iter.c --- b/epan/dissectors/packet-ieee80211-radiotap-iter.c +++ b/epan/dissectors/packet-ieee80211-radiotap-iter.c @@ -120,6 +120,9 @@ struct ieee80211_radiotap_header *radiotap_header, int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns) { + if (max_length < (int)sizeof(struct ieee80211_radiotap_header)) + return -EINVAL; + /* Linux only supports version 0 radiotap format */ if (radiotap_header->it_version) return -EINVAL; @@ -131,6 +134,7 @@ iterator->_bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present); iterator->_arg = (guint8 *)radiotap_header + sizeof(*radiotap_header); iterator->_reset_on_ext = 0; + iterator->_next_ns_data = NULL; iterator->_next_bitmap = &radiotap_header->it_present; iterator->_next_bitmap++; iterator->_vns = vns; @@ -146,9 +150,11 @@ /* find payload start allowing for extended bitmap(s) */ - if (iterator->_bitmap_shifter & (1<_bitmap_shifter & (1U<_arg) & - (1 << IEEE80211_RADIOTAP_EXT)) { + (1U << IEEE80211_RADIOTAP_EXT)) { iterator->_arg += sizeof(guint32); /* @@ -157,7 +163,7 @@ * stated radiotap header length */ - if (!ITERATOR_VALID(iterator, 0)) + if (!ITERATOR_VALID(iterator, sizeof(guint32))) return -EINVAL; } @@ -287,9 +293,14 @@ } if (!align) { /* skip all subsequent data */ + if (!iterator->_next_ns_data) + return -EINVAL; iterator->_arg = iterator->_next_ns_data; /* give up on this namespace */ iterator->current_namespace = NULL; + iterator->_next_ns_data = NULL; + if (!ITERATOR_VALID(iterator, 0)) + return -EINVAL; goto next_entry; } break; diff --git a/epan/dissectors/packet-ieee80211-radiotap.c.old b/epan/dissectors/packet-ieee80211-radiotap.c index fd8ad89..c4945a8 100644 --- a/epan/dissectors/packet-ieee80211-radiotap.c.old +++ b/epan/dissectors/packet-ieee80211-radiotap.c @@ -49,6 +49,7 @@ static int proto_radiotap = -1; static int hf_radiotap_version = -1; static int hf_radiotap_pad = -1; static int hf_radiotap_length = -1; +static int hf_radiotap_invalid_header_length = -1; static int hf_radiotap_present = -1; static int hf_radiotap_mactime = -1; /* static int hf_radiotap_channel = -1; */ @@ -1024,6 +1025,14 @@ dissect_radiotap(tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree) tvb, 2, 2, length); } + /* + * The length is the length of the entire radiotap header, so it + * must be at least 8, for the version, padding, length, and first + * presence flags word. + */ + if (length < 8) + return; + data = ep_tvb_memdup(tvb, 0, length); if (!data) return; @@ -1990,6 +1999,11 @@ void proto_register_radiotap(void) FT_UINT8, BASE_DEC, NULL, 0x0, "Padding", HFILL}}, + {&hf_radiotap_invalid_header_length, + {"Present flags", "radiotap.length.invalid", + FT_NONE, BASE_NONE, NULL, 0x0, + "The radiotap header length is less than 8 bytes", HFILL}}, + {&hf_radiotap_length, {"Header length", "radiotap.length", FT_UINT16, BASE_DEC, NULL, 0x0,