From 1515b211e20354e097092de0b52e50862e64ce36 Mon Sep 17 00:00:00 2001 From: Gerald Combs Date: Thu, 22 Feb 2024 18:50:24 -0800 Subject: [PATCH] SMB2: Add recursion checks --- epan/dissectors/packet-smb2.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/epan/dissectors/packet-smb2.c b/epan/dissectors/packet-smb2.c index e20c99b978..ff1bf5b1e3 100644 --- a/epan/dissectors/packet-smb2.c +++ b/epan/dissectors/packet-smb2.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -1289,6 +1290,7 @@ static const value_string file_full_ea_information_flags[] = { { 0, NULL } }; +#define MAX_RECURSION_DEPTH 10 // Arbitrarily chosen. static int dissect_windows_sockaddr_storage(tvbuff_t *, packet_info *, proto_tree *, int, int); static void dissect_smb2_error_data(tvbuff_t *, packet_info *, proto_tree *, int, int, smb2_info_t *); @@ -4070,6 +4072,7 @@ dissect_smb2_STATUS_STOPPED_ON_SYMLINK(tvbuff_t *tvb, packet_info *pinfo _U_, pr } static int +// NOLINTNEXTLINE(misc-no-recursion) dissect_smb2_error_context(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int offset, smb2_info_t *si _U_) { proto_tree *tree; @@ -4098,6 +4101,7 @@ dissect_smb2_error_context(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *pa * Assumes it is being called with a sub-tvb (dissects at offsets 0) */ static void +// NOLINTNEXTLINE(misc-no-recursion) dissect_smb2_error_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *parent_tree, int error_context_count, int error_id, smb2_info_t *si _U_) @@ -4128,8 +4132,13 @@ dissect_smb2_error_data(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *paren break; } } else { - for (i = 0; i < error_context_count; i++) + unsigned recursion_depth = p_get_proto_depth(pinfo, proto_smb2); + DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH); + p_set_proto_depth(pinfo, proto_smb2, recursion_depth + 1); + for (i = 0; i < error_context_count; i++) { offset += dissect_smb2_error_context(tvb, pinfo, tree, offset, si); + } + p_set_proto_depth(pinfo, proto_smb2, recursion_depth); } } @@ -7460,6 +7469,7 @@ dissect_windows_sockaddr_storage(tvbuff_t *tvb, packet_info *pinfo, proto_tree * #define NETWORK_INTERFACE_CAP_RDMA 0x00000002 static void +// NOLINTNEXTLINE(misc-no-recursion) dissect_smb2_NETWORK_INTERFACE_INFO(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree) { guint32 next_offset; @@ -7541,7 +7551,11 @@ dissect_smb2_NETWORK_INTERFACE_INFO(tvbuff_t *tvb, packet_info *pinfo, proto_tre next_tvb = tvb_new_subset_remaining(tvb, next_offset); /* next extra info */ + unsigned recursion_depth = p_get_proto_depth(pinfo, proto_smb2); + DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH); + p_set_proto_depth(pinfo, proto_smb2, recursion_depth + 1); dissect_smb2_NETWORK_INTERFACE_INFO(next_tvb, pinfo, parent_tree); + p_set_proto_depth(pinfo, proto_smb2, recursion_depth); } } @@ -9444,6 +9458,7 @@ get_create_context_data_tag_dissectors(const char *tag) } static void +// NOLINTNEXTLINE(misc-no-recursion) dissect_smb2_create_extra_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, smb2_info_t *si) { offset_length_buffer_t tag_olb; @@ -9519,7 +9534,11 @@ dissect_smb2_create_extra_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *pa chain_tvb = tvb_new_subset_remaining(tvb, chain_offset); /* next extra info */ + unsigned recursion_depth = p_get_proto_depth(pinfo, proto_smb2); + DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH); + p_set_proto_depth(pinfo, proto_smb2, recursion_depth + 1); dissect_smb2_create_extra_info(chain_tvb, pinfo, parent_tree, si); + p_set_proto_depth(pinfo, proto_smb2, recursion_depth); } } @@ -11343,6 +11362,7 @@ dissect_smb2_signature(packet_info *pinfo, tvbuff_t *tvb, int offset, proto_tree } static int +// NOLINTNEXTLINE(misc-no-recursion) dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolean first_in_chain) { int msg_type; @@ -11386,6 +11406,10 @@ dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolea break; } + unsigned recursion_depth = p_get_proto_depth(pinfo, proto_smb2); + DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH); + p_set_proto_depth(pinfo, proto_smb2, recursion_depth + 1); + /* find which conversation we are part of and get the data for that * conversation */ @@ -11700,6 +11724,7 @@ dissect_smb2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, gboolea offset = dissect_smb2(next_tvb, pinfo, parent_tree, FALSE); } + p_set_proto_depth(pinfo, proto_smb2, recursion_depth); return offset; }