From 646b1313038487f7c04bf0ada7960ad906a01408 Mon Sep 17 00:00:00 2001 From: John Thacker Date: Fri, 10 Mar 2023 22:55:54 -0500 Subject: [PATCH] LISP: Don't go past a LCAF payload length The LISP Canonical Address Format has a payload length indicator. Use that to create a payload tvb and don't dissect outside the payload length. With fuzzed and malformed packets, this was causing the same bytes to be dissected many times, particularly in the recursive address types. A LCAF would be dissected outside the payload region, but then elsewhere the offset was only advanced by the payload length. Fix #18900 (cherry picked from commit b911cf286f495ba068c77b8b2b3445d1a325a819) --- epan/dissectors/packet-lisp.c | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/epan/dissectors/packet-lisp.c b/epan/dissectors/packet-lisp.c index fe93d360c71..e8468c1d8bb 100644 --- a/epan/dissectors/packet-lisp.c +++ b/epan/dissectors/packet-lisp.c @@ -1825,6 +1825,7 @@ dissect_lcaf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, p guint16 len; proto_item *tir, *ti_header, *ti_flags, *ti; proto_tree *lcaf_tree, *lcaf_header_tree, *flags_tree; + tvbuff_t *payload_tvb; len = tvb_get_ntohs(tvb, offset + 4); @@ -1869,46 +1870,47 @@ dissect_lcaf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, p proto_tree_add_item(lcaf_header_tree, hf_lisp_lcaf_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2; + payload_tvb = tvb_new_subset_length(tvb, 0, offset + len); ti = (tip) ? tip : tir; switch (lcaf_type) { case LCAF_NULL: break; case LCAF_AFI_LIST: - offset = dissect_lcaf_afi_list(tvb, pinfo, lcaf_tree, offset, len); + offset = dissect_lcaf_afi_list(payload_tvb, pinfo, lcaf_tree, offset, len); break; case LCAF_IID: - offset = dissect_lcaf_iid(tvb, pinfo, lcaf_tree, offset, ti); + offset = dissect_lcaf_iid(payload_tvb, pinfo, lcaf_tree, offset, ti); break; case LCAF_ASN: - offset = dissect_lcaf_asn(tvb, pinfo, lcaf_tree, offset, ti); + offset = dissect_lcaf_asn(payload_tvb, pinfo, lcaf_tree, offset, ti); break; case LCAF_GEO: - offset = dissect_lcaf_geo(tvb, pinfo, lcaf_tree, offset, ti); + offset = dissect_lcaf_geo(payload_tvb, pinfo, lcaf_tree, offset, ti); break; case LCAF_NATT: - offset = dissect_lcaf_natt(tvb, pinfo, lcaf_tree, offset, len); + offset = dissect_lcaf_natt(payload_tvb, pinfo, lcaf_tree, offset, len); break; case LCAF_NONCE_LOC: - offset = dissect_lcaf_nonce_loc(tvb, pinfo, lcaf_tree, offset, ti); + offset = dissect_lcaf_nonce_loc(payload_tvb, pinfo, lcaf_tree, offset, ti); break; case LCAF_MCAST_INFO: - offset = dissect_lcaf_mcast_info(tvb, pinfo, lcaf_tree, offset, ti); + offset = dissect_lcaf_mcast_info(payload_tvb, pinfo, lcaf_tree, offset, ti); break; case LCAF_ELP: - offset = dissect_lcaf_elp(tvb, pinfo, lcaf_tree, offset, len, ti); + offset = dissect_lcaf_elp(payload_tvb, pinfo, lcaf_tree, offset, len, ti); break; case LCAF_SRC_DST_KEY: - offset = dissect_lcaf_src_dst_key(tvb, pinfo, lcaf_tree, offset, ti); + offset = dissect_lcaf_src_dst_key(payload_tvb, pinfo, lcaf_tree, offset, ti); break; case LCAF_RLE: - offset = dissect_lcaf_rle(tvb, pinfo, lcaf_tree, offset, len, ti); + offset = dissect_lcaf_rle(payload_tvb, pinfo, lcaf_tree, offset, len, ti); break; case LCAF_KV_ADDR_PAIR: - offset = dissect_lcaf_kv_addr_pair(tvb, pinfo, lcaf_tree, offset); + offset = dissect_lcaf_kv_addr_pair(payload_tvb, pinfo, lcaf_tree, offset); break; case LCAF_VENDOR: - offset = dissect_lcaf_vendor(tvb, pinfo, lcaf_tree, offset, len); + offset = dissect_lcaf_vendor(payload_tvb, pinfo, lcaf_tree, offset, len); break; default: proto_tree_add_expert(tree, pinfo, &ei_lisp_undecoded, tvb, offset, len); -- GitLab