AllJoyn: Add recursion checks

This commit is contained in:
Gerald Combs 2024-02-21 15:01:00 -08:00
parent 34c90f7a3d
commit 8b0e90d62e
1 changed files with 33 additions and 6 deletions

View File

@ -11,6 +11,7 @@
#include "config.h"
#include <epan/packet.h>
#include <proto_data.h>
#include <epan/expert.h>
#include <wsutil/ws_roundup.h>
#include <wsutil/str_util.h>
@ -29,6 +30,9 @@ static dissector_handle_t alljoyn_handle_ardp;
/* DBus limits packet length to 2^27. AllJoyn limits it further to 2^17 + 4096 to allow for 2^17 payload */
#define MAX_PACKET_LEN (MAX_ARRAY_LEN + 4096)
/* Arbitrarily chosen. */
#define MAX_RECURSION_DEPTH 10
/* The following are protocols within a frame.
The actual value of the handle is set when the various fields are
registered in proto_register_AllJoyn() with a call to
@ -769,13 +773,17 @@ append_struct_signature(proto_item *item,
* @param signature_length is a pointer to the length of the signature.
*/
static void
advance_to_end_of_signature(const guint8 **signature,
guint8 *signature_length)
// NOLINTNEXTLINE(misc-no-recursion)
advance_to_end_of_signature(packet_info *pinfo, const guint8 **signature, guint8 *signature_length)
{
gboolean done = FALSE;
gint8 current_type;
gint8 end_type = ARG_INVALID;
unsigned recursion_depth = p_get_proto_depth(pinfo, proto_AllJoyn_mess);
DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
p_set_proto_depth(pinfo, proto_AllJoyn_mess, recursion_depth + 1);
while (*signature_length > 0 && **signature && !done) {
current_type = *(++(*signature));
--*signature_length;
@ -792,15 +800,15 @@ advance_to_end_of_signature(const guint8 **signature,
switch(current_type)
{
case ARG_ARRAY:
advance_to_end_of_signature(signature, signature_length);
advance_to_end_of_signature(pinfo, signature, signature_length);
break;
case ARG_STRUCT:
end_type = ')';
advance_to_end_of_signature(signature, signature_length);
advance_to_end_of_signature(pinfo, signature, signature_length);
break;
case ARG_DICT_ENTRY:
end_type = '}';
advance_to_end_of_signature(signature, signature_length);
advance_to_end_of_signature(pinfo, signature, signature_length);
break;
case ARG_BYTE:
@ -825,6 +833,7 @@ advance_to_end_of_signature(const guint8 **signature,
break;
}
}
p_set_proto_depth(pinfo, proto_AllJoyn_mess, recursion_depth);
}
/* This is called to add a padding item. There is not padding done for each call made.
@ -877,6 +886,7 @@ static void add_padding_item(gint padding_start, gint padding_end, tvbuff_t *tvb
* parameters come in.
*/
static gint
// NOLINTNEXTLINE(misc-no-recursion)
parse_arg(tvbuff_t *tvb,
packet_info *pinfo,
proto_item *header_item,
@ -941,10 +951,14 @@ parse_arg(tvbuff_t *tvb,
add_padding_item(padding_start, offset, tvb, tree);
if(0 == length) {
advance_to_end_of_signature(signature, signature_length);
advance_to_end_of_signature(pinfo, signature, signature_length);
} else {
guint8 sig_length_saved = *signature_length - 1;
unsigned recursion_depth = p_get_proto_depth(pinfo, proto_AllJoyn_mess);
DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
p_set_proto_depth(pinfo, proto_AllJoyn_mess, recursion_depth + 1);
while((offset - starting_offset) < length) {
const guint8 *sig_pointer;
guint8 remaining_sig_length;
@ -970,6 +984,7 @@ parse_arg(tvbuff_t *tvb,
*signature = sig_pointer;
*signature_length = remaining_sig_length;
}
p_set_proto_depth(pinfo, proto_AllJoyn_mess, recursion_depth);
}
if(item) {
@ -1180,14 +1195,20 @@ parse_arg(tvbuff_t *tvb,
offset += length;
sig_pointer = sig_saved;
unsigned recursion_depth = p_get_proto_depth(pinfo, proto_AllJoyn_mess);
DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
p_set_proto_depth(pinfo, proto_AllJoyn_mess, recursion_depth + 1);
/* The signature of the variant has now been taken care of. So now take care of the variant data. */
while(((sig_pointer - sig_saved) < (length - 1)) && (tvb_reported_length_remaining(tvb, offset) > 0)) {
proto_item_append_text(item, "%c", g_ascii_isprint(*sig_pointer) ? *sig_pointer : '?');
offset = parse_arg(tvb, pinfo, header_item, encoding, offset, tree, is_reply_to,
*sig_pointer, field_code, &sig_pointer, &variant_sig_length, field_starting_offset);
}
p_set_proto_depth(pinfo, proto_AllJoyn_mess, recursion_depth);
proto_item_append_text(item, "'");
proto_item_set_end(item, tvb, offset);
}
@ -1241,6 +1262,10 @@ parse_arg(tvbuff_t *tvb,
(*signature)++; /* Advance past the '(' or '{'. */
(*signature_length)--;
unsigned recursion_depth = p_get_proto_depth(pinfo, proto_AllJoyn_mess);
DISSECTOR_ASSERT(recursion_depth <= MAX_RECURSION_DEPTH);
p_set_proto_depth(pinfo, proto_AllJoyn_mess, recursion_depth + 1);
/* *signature should never be NULL but just make sure to avoid potential issues. */
while(*signature && **signature && **signature != type_stop
&& tvb_reported_length_remaining(tvb, offset) > 0) {
@ -1258,6 +1283,8 @@ parse_arg(tvbuff_t *tvb,
field_starting_offset);
}
p_set_proto_depth(pinfo, proto_AllJoyn_mess, recursion_depth);
proto_item_set_end(item, tvb, offset);
}
break;