Quick and dirty overflow checking.

We really need a better way to handle packet offset overflows.

Change-Id: I6e476f7bc6ddac2c5515c4e09192d88f528ea091
Reviewed-on: https://code.wireshark.org/review/9194
Reviewed-by: Guy Harris <guy@alum.mit.edu>
This commit is contained in:
Guy Harris 2015-06-27 15:29:37 -07:00
parent 74a5f50c80
commit 80efc53b05
1 changed files with 29 additions and 4 deletions

View File

@ -32,6 +32,7 @@
#include <epan/uat.h> #include <epan/uat.h>
#include <epan/tap.h> #include <epan/tap.h>
#include <epan/conversation.h> #include <epan/conversation.h>
#include <epan/exceptions.h>
#include <epan/to_str.h> #include <epan/to_str.h>
#ifndef HAVE_INET_ATON #ifndef HAVE_INET_ATON
#include <wsutil/inet_aton.h> #include <wsutil/inet_aton.h>
@ -124,9 +125,18 @@ static guint32 aeron_pos_delta(const aeron_pos_t * pos1, const aeron_pos_t * pos
return ((guint32) (delta & G_GUINT64_CONSTANT(0x00000000ffffffff))); return ((guint32) (delta & G_GUINT64_CONSTANT(0x00000000ffffffff)));
} }
static void aeron_pos_add_length(aeron_pos_t * pos, guint32 length, guint32 term_length) static gboolean aeron_pos_add_length(aeron_pos_t * pos, guint32 length, guint32 term_length)
{ {
guint32 next_term_offset = aeron_pos_roundup(pos->term_offset + length); guint32 next_term_offset;
guint32 rounded_next_term_offset;
next_term_offset = pos->term_offset + length;
if (next_term_offset < pos->term_offset)
return FALSE; /* overflow */
rounded_next_term_offset = aeron_pos_roundup(next_term_offset);
if (rounded_next_term_offset < next_term_offset)
return FALSE; /* overflow */
next_term_offset = rounded_next_term_offset;
if (next_term_offset >= term_length) if (next_term_offset >= term_length)
{ {
@ -137,6 +147,7 @@ static void aeron_pos_add_length(aeron_pos_t * pos, guint32 length, guint32 term
{ {
pos->term_offset = next_term_offset; pos->term_offset = next_term_offset;
} }
return TRUE;
} }
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
@ -1249,7 +1260,8 @@ static void aeron_frame_stream_analysis_setup(packet_info * pinfo, aeron_packet_
case HDR_TYPE_PAD: case HDR_TYPE_PAD:
dp.term_id = info->term_id; dp.term_id = info->term_id;
dp.term_offset = info->term_offset; dp.term_offset = info->term_offset;
aeron_pos_add_length(&dp, info->length, stream->term_length); if (!aeron_pos_add_length(&dp, info->length, stream->term_length))
THROW(ReportedBoundsError);
if (pdpv) if (pdpv)
{ {
if (dp.term_id > stream->high.term_id) if (dp.term_id > stream->high.term_id)
@ -1377,7 +1389,8 @@ static void aeron_frame_stream_analysis_setup(packet_info * pinfo, aeron_packet_
expected_dp.term_id = pdp.term_id; expected_dp.term_id = pdp.term_id;
expected_dp.term_offset = pdp.term_offset; expected_dp.term_offset = pdp.term_offset;
aeron_pos_add_length(&expected_dp, info->length, stream->term_length); if (!aeron_pos_add_length(&expected_dp, info->length, stream->term_length))
THROW(ReportedBoundsError);
erc = aeron_pos_compare(&expected_dp, &dp); erc = aeron_pos_compare(&expected_dp, &dp);
if (erc > 0) if (erc > 0)
{ {
@ -2186,6 +2199,8 @@ static int dissect_aeron_pad(tvbuff_t * tvb, int offset, packet_info * pinfo, pr
frame_length = tvb_get_letohl(tvb, offset + O_AERON_PAD_FRAME_LENGTH); frame_length = tvb_get_letohl(tvb, offset + O_AERON_PAD_FRAME_LENGTH);
rounded_length = (int) aeron_pos_roundup(frame_length); rounded_length = (int) aeron_pos_roundup(frame_length);
if (rounded_length < 0)
THROW(ReportedBoundsError);
term_offset = tvb_get_letohl(tvb, offset + O_AERON_PAD_TERM_OFFSET); term_offset = tvb_get_letohl(tvb, offset + O_AERON_PAD_TERM_OFFSET);
session_id = tvb_get_letohl(tvb, offset + O_AERON_PAD_SESSION_ID); session_id = tvb_get_letohl(tvb, offset + O_AERON_PAD_SESSION_ID);
transport = aeron_transport_add(cinfo, session_id, pinfo->fd->num); transport = aeron_transport_add(cinfo, session_id, pinfo->fd->num);
@ -2325,6 +2340,8 @@ static int dissect_aeron_data(tvbuff_t * tvb, int offset, packet_info * pinfo, p
{ {
offset_increment = aeron_pos_roundup(frame_length); offset_increment = aeron_pos_roundup(frame_length);
rounded_length = (int) offset_increment; rounded_length = (int) offset_increment;
if (rounded_length < 0)
THROW(ReportedBoundsError);
data_length = frame_length - O_AERON_DATA_DATA; data_length = frame_length - O_AERON_DATA_DATA;
} }
term_offset = tvb_get_letohl(tvb, offset + O_AERON_DATA_TERM_OFFSET); term_offset = tvb_get_letohl(tvb, offset + O_AERON_DATA_TERM_OFFSET);
@ -2429,6 +2446,8 @@ static int dissect_aeron_nak(tvbuff_t * tvb, int offset, packet_info * pinfo, pr
frame_length = tvb_get_letohl(tvb, offset + O_AERON_NAK_FRAME_LENGTH); frame_length = tvb_get_letohl(tvb, offset + O_AERON_NAK_FRAME_LENGTH);
rounded_length = (int) aeron_pos_roundup(frame_length); rounded_length = (int) aeron_pos_roundup(frame_length);
if (rounded_length < 0)
THROW(ReportedBoundsError);
session_id = tvb_get_letohl(tvb, offset + O_AERON_NAK_SESSION_ID); session_id = tvb_get_letohl(tvb, offset + O_AERON_NAK_SESSION_ID);
transport = aeron_transport_add(cinfo, session_id, pinfo->fd->num); transport = aeron_transport_add(cinfo, session_id, pinfo->fd->num);
stream_id = tvb_get_letohl(tvb, offset + O_AERON_NAK_STREAM_ID); stream_id = tvb_get_letohl(tvb, offset + O_AERON_NAK_STREAM_ID);
@ -2511,6 +2530,8 @@ static int dissect_aeron_sm(tvbuff_t * tvb, int offset, packet_info * pinfo, pro
frame_length = tvb_get_letohl(tvb, offset + O_AERON_SM_FRAME_LENGTH); frame_length = tvb_get_letohl(tvb, offset + O_AERON_SM_FRAME_LENGTH);
feedback_length = frame_length - O_AERON_SM_FEEDBACK; feedback_length = frame_length - O_AERON_SM_FEEDBACK;
rounded_length = (int) aeron_pos_roundup(frame_length); rounded_length = (int) aeron_pos_roundup(frame_length);
if (rounded_length < 0)
THROW(ReportedBoundsError);
session_id = tvb_get_letohl(tvb, offset + O_AERON_SM_SESSION_ID); session_id = tvb_get_letohl(tvb, offset + O_AERON_SM_SESSION_ID);
transport = aeron_transport_add(cinfo, session_id, pinfo->fd->num); transport = aeron_transport_add(cinfo, session_id, pinfo->fd->num);
stream_id = tvb_get_letohl(tvb, offset + O_AERON_SM_STREAM_ID); stream_id = tvb_get_letohl(tvb, offset + O_AERON_SM_STREAM_ID);
@ -2603,6 +2624,8 @@ static int dissect_aeron_err(tvbuff_t * tvb, int offset, packet_info * pinfo, pr
proto_tree_add_item(subtree, hf_aeron_err_string, tvb, offset + ofs, string_length, ENC_ASCII|ENC_NA); proto_tree_add_item(subtree, hf_aeron_err_string, tvb, offset + ofs, string_length, ENC_ASCII|ENC_NA);
} }
rounded_length = (int) aeron_pos_roundup(frame_length); rounded_length = (int) aeron_pos_roundup(frame_length);
if (rounded_length < 0)
THROW(ReportedBoundsError);
proto_item_set_len(err_item, rounded_length); proto_item_set_len(err_item, rounded_length);
if (frame_length < L_AERON_ERR_MIN) if (frame_length < L_AERON_ERR_MIN)
{ {
@ -2648,6 +2671,8 @@ static int dissect_aeron_setup(tvbuff_t * tvb, int offset, packet_info * pinfo,
frame_length = tvb_get_letohl(tvb, offset + O_AERON_SETUP_FRAME_LENGTH); frame_length = tvb_get_letohl(tvb, offset + O_AERON_SETUP_FRAME_LENGTH);
rounded_length = (int) aeron_pos_roundup(frame_length); rounded_length = (int) aeron_pos_roundup(frame_length);
if (rounded_length < 0)
THROW(ReportedBoundsError);
term_offset = tvb_get_letohl(tvb, offset + O_AERON_SETUP_TERM_OFFSET); term_offset = tvb_get_letohl(tvb, offset + O_AERON_SETUP_TERM_OFFSET);
session_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_SESSION_ID); session_id = tvb_get_letohl(tvb, offset + O_AERON_SETUP_SESSION_ID);
transport = aeron_transport_add(cinfo, session_id, pinfo->fd->num); transport = aeron_transport_add(cinfo, session_id, pinfo->fd->num);