diff options
author | Pascal Quantin <pascal.quantin@gmail.com> | 2018-03-05 21:51:11 +0100 |
---|---|---|
committer | Alexis La Goutte <alexis.lagoutte@gmail.com> | 2018-03-06 07:20:55 +0000 |
commit | b434e0a03be45ed796af7271972672a0b43cffa8 (patch) | |
tree | 77a421963d41c12d9f9e4ea14bd617c4e723ee9d /epan/dissectors/packet-vlan.c | |
parent | c39dbd68d472046cf97211c86267e0305630d934 (diff) |
VLAN: define a recursion depth limit
Altough the dissection consumes 4 bytes each time it is called, it can
trigger a stack overflow for big packets. Let's limmit the number of
allowed VLAN tags for a given packet.
Bug: 14469
Change-Id: Ieb6834ab3350dc7e8c301e6479577855a253897e
Reviewed-on: https://code.wireshark.org/review/26270
Petri-Dish: Pascal Quantin <pascal.quantin@gmail.com>
Tested-by: Petri Dish Buildbot
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Diffstat (limited to 'epan/dissectors/packet-vlan.c')
-rw-r--r-- | epan/dissectors/packet-vlan.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/epan/dissectors/packet-vlan.c b/epan/dissectors/packet-vlan.c index 00d75bf2d9..8f23257465 100644 --- a/epan/dissectors/packet-vlan.c +++ b/epan/dissectors/packet-vlan.c @@ -23,6 +23,7 @@ #include <epan/prefs.h> #include <epan/to_str.h> #include <epan/addr_resolv.h> +#include <epan/proto_data.h> void proto_register_vlan(void); void proto_reg_handoff_vlan(void); @@ -54,6 +55,8 @@ static dissector_handle_t ethertype_handle; static capture_dissector_handle_t llc_cap_handle; static capture_dissector_handle_t ipx_cap_handle; +static int proto_vlan; + static header_field_info *hfi_vlan = NULL; #define VLAN_HFI_INIT HFI_INIT(proto_vlan) @@ -184,6 +187,9 @@ static header_field_info hfi_vlan_trailer VLAN_HFI_INIT = { static gint ett_vlan = -1; static expert_field ei_vlan_len = EI_INIT; +static expert_field ei_vlan_too_many_tags = EI_INIT; + +#define VLAN_MAX_NESTED_TAGS 10 static gboolean capture_vlan(const guchar *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header _U_ ) { @@ -231,6 +237,7 @@ dissect_vlan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ gboolean is_802_2; proto_tree *vlan_tree; proto_item *item; + guint vlan_nested_count; col_set_str(pinfo->cinfo, COL_PROTOCOL, "VLAN"); col_clear(pinfo->cinfo, COL_INFO); @@ -246,8 +253,15 @@ dissect_vlan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_ vlan_tree = NULL; + ti = proto_tree_add_item(tree, hfi_vlan, tvb, 0, 4, ENC_NA); + vlan_nested_count = GPOINTER_TO_UINT(p_get_proto_data(pinfo->pool, pinfo, proto_vlan, 0)); + if (++vlan_nested_count > VLAN_MAX_NESTED_TAGS) { + expert_add_info(pinfo, ti, &ei_vlan_too_many_tags); + return tvb_captured_length(tvb); + } + p_add_proto_data(pinfo->pool, pinfo, proto_vlan, 0, GUINT_TO_POINTER(vlan_nested_count)); + if (tree) { - ti = proto_tree_add_item(tree, hfi_vlan, tvb, 0, 4, ENC_NA); if (vlan_summary_in_tree) { if (vlan_version < IEEE_8021Q_2011) { @@ -364,6 +378,7 @@ proto_register_vlan(void) static ei_register_info ei[] = { { &ei_vlan_len, { "vlan.len.past_end", PI_MALFORMED, PI_ERROR, "Length field value goes past the end of the payload", EXPFILL }}, + { &ei_vlan_too_many_tags, { "vlan.too_many_tags", PI_UNDECODED, PI_WARN, "Too many nested VLAN tags", EXPFILL }}, }; static const enum_val_t version_vals[] = { @@ -383,7 +398,6 @@ proto_register_vlan(void) module_t *vlan_module; expert_module_t* expert_vlan; - int proto_vlan; proto_vlan = proto_register_protocol("802.1Q Virtual LAN", "VLAN", "vlan"); hfi_vlan = proto_registrar_get_nth(proto_vlan); |