From: Tom Peters (thopeter) Date: Tue, 18 May 2021 21:05:04 +0000 (+0000) Subject: Merge pull request #2885 in SNORT/snort3 from ~MDAGON/snort3:res_depth to master X-Git-Tag: 3.1.5.0~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6369f62a867b23ac1dc328a78f6625d5bc0d452c;p=thirdparty%2Fsnort3.git Merge pull request #2885 in SNORT/snort3 from ~MDAGON/snort3:res_depth to master Squashed commit of the following: commit 94b659b9e667930660a9434d0c9a514d3b187617 Author: Maya Dagon Date: Fri Apr 23 11:03:32 2021 -0400 http2_inspect: optimize processing after reaching flow depth --- diff --git a/src/service_inspectors/http2_inspect/http2_stream.h b/src/service_inspectors/http2_inspect/http2_stream.h index ec0209f28..e9e4e65bb 100644 --- a/src/service_inspectors/http2_inspect/http2_stream.h +++ b/src/service_inspectors/http2_inspect/http2_stream.h @@ -58,6 +58,10 @@ public: { return end_stream_on_data_flush[source_id]; } void finish_msg_body(HttpCommon::SourceId source_id, bool expect_trailers, bool clear_partial_buffer); + void set_discard(HttpCommon::SourceId source_id) + { discard[source_id] = true; } + bool is_discard_set(HttpCommon::SourceId source_id) + { return discard[source_id]; } #ifdef REG_TEST void print_frame(FILE* output); @@ -71,6 +75,7 @@ private: bool end_stream_on_data_flush[2] = { false, false }; Http2Enums::StreamState state[2] = { Http2Enums::STREAM_EXPECT_HEADERS, Http2Enums::STREAM_EXPECT_HEADERS }; + bool discard[2] = { false, false }; }; #endif diff --git a/src/service_inspectors/http2_inspect/http2_stream_splitter.h b/src/service_inspectors/http2_inspect/http2_stream_splitter.h index 38248e4ee..624aa70da 100644 --- a/src/service_inspectors/http2_inspect/http2_stream_splitter.h +++ b/src/service_inspectors/http2_inspect/http2_stream_splitter.h @@ -60,7 +60,7 @@ private: HttpCommon::SourceId source_id); static bool read_frame_hdr(Http2FlowData* session_data, const uint8_t* data, uint32_t length, HttpCommon::SourceId source_id, uint32_t& data_offset); - static void discarded_data_frame_cleanup(Http2FlowData* session_data, HttpCommon::SourceId source_id); + static void discarded_data_frame_cleanup(Http2FlowData* session_data, HttpCommon::SourceId source_id, Http2Stream* stream); }; diff --git a/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc b/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc index 98ab536db..964fdd596 100644 --- a/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc +++ b/src/service_inspectors/http2_inspect/http2_stream_splitter_impl.cc @@ -331,14 +331,14 @@ StreamSplitter::Status Http2StreamSplitter::implement_scan(Http2FlowData* sessio { Http2Stream* const stream = session_data->find_stream(session_data->current_stream[source_id]); - if (stream && stream->is_open(source_id)) + if (stream && stream->is_open(source_id) && !stream->is_discard_set(source_id)) { status = session_data->data_cutter[source_id].scan( data, length, flush_offset, data_offset, frame_flags); } else { - // Need to skip past Data frame in a bad stream + // Need to skip past Data frame in a bad stream or if passed flow depth uint32_t& remaining = session_data->scan_remaining_frame_octets[source_id]; if (length - data_offset < remaining) { @@ -351,9 +351,18 @@ StreamSplitter::Status Http2StreamSplitter::implement_scan(Http2FlowData* sessio remaining = 0; session_data->header_octets_seen[source_id] = 0; session_data->scan_state[source_id] = SCAN_FRAME_HEADER; - assert(!session_data->frame_lengths[source_id].empty()); - session_data->frame_lengths[source_id].pop(); - assert(session_data->frame_lengths[source_id].empty()); + + if (!session_data->frame_lengths[source_id].empty()) + { + session_data->frame_lengths[source_id].pop(); + assert(session_data->frame_lengths[source_id].empty()); + } + + if (stream && ((frame_flags & FLAG_END_STREAM) != 0)) + { + stream->set_end_stream_on_data_flush(source_id); + discarded_data_frame_cleanup(session_data, source_id, stream); + } } session_data->payload_discard[source_id] = true; @@ -501,38 +510,42 @@ const StreamBuffer Http2StreamSplitter::implement_reassemble(Http2FlowData* sess session_data->frame_reassemble[source_id] = nullptr; } - if (session_data->frame_type[source_id] != FT_DATA || - session_data->frame_data[source_id] != nullptr) + if (session_data->frame_type[source_id] == FT_DATA && + session_data->frame_data[source_id] == nullptr) + { + Http2Stream* const stream = + session_data->find_stream(session_data->current_stream[source_id]); + if (stream) + { + stream->set_discard(source_id); + discarded_data_frame_cleanup(session_data, source_id, stream); + } + } + else { // Return 0-length non-null buffer to stream which signals detection required, // but don't create pkt_data buffer frame_buf.data = (const uint8_t*)""; } - else - discarded_data_frame_cleanup(session_data, source_id); } return frame_buf; } -void Http2StreamSplitter::discarded_data_frame_cleanup(Http2FlowData* session_data, HttpCommon::SourceId source_id) +void Http2StreamSplitter::discarded_data_frame_cleanup(Http2FlowData* session_data, HttpCommon::SourceId source_id, Http2Stream* stream) { - Http2Stream* const stream = session_data->find_current_stream(source_id); - - if (!stream || stream->get_state(source_id) == STREAM_ERROR) + if (stream->get_state(source_id) == STREAM_ERROR || + !stream->is_end_stream_on_data_flush(source_id)) return; - if (stream->is_end_stream_on_data_flush(source_id)) + if (session_data->concurrent_files > 0) + session_data->concurrent_files -= 1; + stream->set_state(source_id, STREAM_COMPLETE); + stream->check_and_cleanup_completed(); + if (session_data->delete_stream) { - if (session_data->concurrent_files > 0) - session_data->concurrent_files -= 1; - stream->set_state(source_id, STREAM_COMPLETE); - stream->check_and_cleanup_completed(); - if (session_data->delete_stream) - { - session_data->processing_stream_id = session_data->get_current_stream_id(source_id); - session_data->delete_processing_stream(); - session_data->processing_stream_id = NO_STREAM_ID; - } + session_data->processing_stream_id = session_data->get_current_stream_id(source_id); + session_data->delete_processing_stream(); + session_data->processing_stream_id = NO_STREAM_ID; } }