From: Victor Julien Date: Wed, 13 Apr 2022 05:42:09 +0000 (+0200) Subject: stream: make raw data handling more generally usable X-Git-Tag: suricata-7.0.0-beta1~740 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=96bc11d0d0f908bc526fa12ec975e32d05e915dd;p=thirdparty%2Fsuricata.git stream: make raw data handling more generally usable Move raw detection logic out of main StreamReassembleRawDo() so that it can be reused for other parts of the engine. The caller now has to specify a right edge of the data. --- diff --git a/src/stream-tcp-reassemble.c b/src/stream-tcp-reassemble.c index 0d74459fd1..750d304142 100644 --- a/src/stream-tcp-reassemble.c +++ b/src/stream-tcp-reassemble.c @@ -1648,6 +1648,7 @@ static int StreamReassembleRawInline(TcpSession *ssn, const Packet *p, * \param Callback the function pointer to the callback function * \param cb_data callback data * \param[in] progress_in progress to work from + * \param[in] re right edge of data to consider * \param[out] progress_out absolute progress value of the data this * call handled. * \param eof we're wrapping up so inspect all data we have, incl unACKd @@ -1657,48 +1658,14 @@ static int StreamReassembleRawInline(TcpSession *ssn, const Packet *p, * much data. */ static int StreamReassembleRawDo(TcpSession *ssn, TcpStream *stream, - StreamReassembleRawFunc Callback, void *cb_data, - const uint64_t progress_in, - uint64_t *progress_out, bool eof, - bool respect_inspect_depth) + StreamReassembleRawFunc Callback, void *cb_data, const uint64_t progress_in, + const uint64_t re, uint64_t *progress_out, bool eof, bool respect_inspect_depth) { SCEnter(); int r = 0; StreamingBufferBlock *iter = NULL; uint64_t progress = progress_in; - /* absolute right edge of ack'd data */ - const uint64_t last_ack_abs = GetAbsLastAck(stream); - SCLogDebug("last_ack_abs %" PRIu64, last_ack_abs); - - /* if the app layer triggered a flush, and we're supposed to - * use a minimal inspect depth, we actually take the app progress - * as that is the right edge of the data. Then we take the window - * of 'min_inspect_depth' before that. */ - - SCLogDebug("respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s stream->min_inspect_depth %u", - respect_inspect_depth ? "true" : "false", - (stream->flags & STREAMTCP_STREAM_FLAG_TRIGGER_RAW) ? "true" : "false", - stream->min_inspect_depth); - - if (respect_inspect_depth && - (stream->flags & STREAMTCP_STREAM_FLAG_TRIGGER_RAW) - && stream->min_inspect_depth) - { - progress = STREAM_APP_PROGRESS(stream); - if (stream->min_inspect_depth >= progress) { - progress = 0; - } else { - progress -= stream->min_inspect_depth; - } - - SCLogDebug("stream app %"PRIu64", raw %"PRIu64, STREAM_APP_PROGRESS(stream), STREAM_RAW_PROGRESS(stream)); - - progress = MIN(progress, STREAM_RAW_PROGRESS(stream)); - SCLogDebug("applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress %"PRIu64, progress); - } - - SCLogDebug("progress %"PRIu64", min inspect depth %u %s", progress, stream->min_inspect_depth, stream->flags & STREAMTCP_STREAM_FLAG_TRIGGER_RAW ? "STREAMTCP_STREAM_FLAG_TRIGGER_RAW":"(no trigger)"); /* loop through available buffers. On no packet loss we'll have a single * iteration. On missing data we'll walk the blocks */ @@ -1721,23 +1688,23 @@ static int StreamReassembleRawDo(TcpSession *ssn, TcpStream *stream, if (eof) { // inspect all remaining data, ack'd or not } else { - if (last_ack_abs < progress) { + if (re < progress) { SCLogDebug("nothing to do"); goto end; } - SCLogDebug("last_ack_abs %"PRIu64", raw_progress %"PRIu64, last_ack_abs, progress); - SCLogDebug("raw_progress + mydata_len %"PRIu64", last_ack_abs %"PRIu64, progress + mydata_len, last_ack_abs); + SCLogDebug("re %" PRIu64 ", raw_progress %" PRIu64, re, progress); + SCLogDebug("raw_progress + mydata_len %" PRIu64 ", re %" PRIu64, progress + mydata_len, + re); /* see if the buffer contains unack'd data as well */ - if (progress + mydata_len > last_ack_abs) { + if (progress + mydata_len > re) { uint32_t check = mydata_len; - mydata_len = last_ack_abs - progress; + mydata_len = re - progress; BUG_ON(check < mydata_len); SCLogDebug("data len adjusted to %u to make sure only ACK'd " "data is considered", mydata_len); } - } if (mydata_len == 0) break; @@ -1756,9 +1723,9 @@ static int StreamReassembleRawDo(TcpSession *ssn, TcpStream *stream, SCLogDebug("raw progress now %"PRIu64, progress); /* data is beyond the progress we'd like, and before last ack. Gap. */ - } else if (mydata_offset > progress && mydata_offset < last_ack_abs) { + } else if (mydata_offset > progress && mydata_offset < re) { SCLogDebug("GAP: data is missing from %"PRIu64" (%u bytes), setting to first data we have: %"PRIu64, progress, (uint32_t)(mydata_offset - progress), mydata_offset); - SCLogDebug("last_ack_abs %"PRIu64, last_ack_abs); + SCLogDebug("re %" PRIu64, re); progress = mydata_offset; SCLogDebug("raw progress now %"PRIu64, progress); @@ -1798,9 +1765,46 @@ int StreamReassembleRaw(TcpSession *ssn, const Packet *p, return 0; } - return StreamReassembleRawDo(ssn, stream, Callback, cb_data, - STREAM_RAW_PROGRESS(stream), progress_out, - (p->flags & PKT_PSEUDO_STREAM_END), respect_inspect_depth); + uint64_t progress = STREAM_RAW_PROGRESS(stream); + /* if the app layer triggered a flush, and we're supposed to + * use a minimal inspect depth, we actually take the app progress + * as that is the right edge of the data. Then we take the window + * of 'min_inspect_depth' before that. */ + + SCLogDebug("respect_inspect_depth %s STREAMTCP_STREAM_FLAG_TRIGGER_RAW %s " + "stream->min_inspect_depth %u", + respect_inspect_depth ? "true" : "false", + (stream->flags & STREAMTCP_STREAM_FLAG_TRIGGER_RAW) ? "true" : "false", + stream->min_inspect_depth); + + if (respect_inspect_depth && (stream->flags & STREAMTCP_STREAM_FLAG_TRIGGER_RAW) && + stream->min_inspect_depth) { + progress = STREAM_APP_PROGRESS(stream); + if (stream->min_inspect_depth >= progress) { + progress = 0; + } else { + progress -= stream->min_inspect_depth; + } + + SCLogDebug("stream app %" PRIu64 ", raw %" PRIu64, STREAM_APP_PROGRESS(stream), + STREAM_RAW_PROGRESS(stream)); + + progress = MIN(progress, STREAM_RAW_PROGRESS(stream)); + SCLogDebug("applied min inspect depth due to STREAMTCP_STREAM_FLAG_TRIGGER_RAW: progress " + "%" PRIu64, + progress); + } + + SCLogDebug("progress %" PRIu64 ", min inspect depth %u %s", progress, stream->min_inspect_depth, + stream->flags & STREAMTCP_STREAM_FLAG_TRIGGER_RAW ? "STREAMTCP_STREAM_FLAG_TRIGGER_RAW" + : "(no trigger)"); + + /* absolute right edge of ack'd data */ + const uint64_t last_ack_abs = GetAbsLastAck(stream); + SCLogDebug("last_ack_abs %" PRIu64, last_ack_abs); + + return StreamReassembleRawDo(ssn, stream, Callback, cb_data, progress, last_ack_abs, + progress_out, (p->flags & PKT_PSEUDO_STREAM_END), respect_inspect_depth); } int StreamReassembleLog(TcpSession *ssn, TcpStream *stream, @@ -1811,8 +1815,12 @@ int StreamReassembleLog(TcpSession *ssn, TcpStream *stream, if (stream->flags & (STREAMTCP_STREAM_FLAG_NOREASSEMBLY)) return 0; - return StreamReassembleRawDo(ssn, stream, Callback, cb_data, - progress_in, progress_out, eof, false); + /* absolute right edge of ack'd data */ + const uint64_t last_ack_abs = GetAbsLastAck(stream); + SCLogDebug("last_ack_abs %" PRIu64, last_ack_abs); + + return StreamReassembleRawDo( + ssn, stream, Callback, cb_data, progress_in, last_ack_abs, progress_out, eof, false); } /** \internal