From: Michael Altizer (mialtize) Date: Wed, 12 Sep 2018 19:12:16 +0000 (-0400) Subject: Merge pull request #1342 in SNORT/snort3 from stream_cleanup to master X-Git-Tag: 3.0.0-248~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d0a10c188597f19790853e66ebb3a50d32bb0195;p=thirdparty%2Fsnort3.git Merge pull request #1342 in SNORT/snort3 from stream_cleanup to master Squashed commit of the following: commit e2e541448233efbeb6e41530b8e4f99edad5af9a Author: Carter Waxman Date: Mon Aug 13 12:33:04 2018 -0400 DetectionEngine: added post-onload callbacks --- diff --git a/src/detection/detection_engine.cc b/src/detection/detection_engine.cc index 79481ec1c..10606d65d 100644 --- a/src/detection/detection_engine.cc +++ b/src/detection/detection_engine.cc @@ -82,6 +82,7 @@ DetectionEngine::~DetectionEngine() { finish_packet(context->packet); sw->complete(); + context->post_detection(); } } @@ -307,6 +308,7 @@ void DetectionEngine::onload() InspectorManager::clear(p); sw->complete(); + c->post_detection(); } bool DetectionEngine::offload(Packet* p) diff --git a/src/detection/ips_context.cc b/src/detection/ips_context.cc index ac07d74e9..75c3f6fb1 100644 --- a/src/detection/ips_context.cc +++ b/src/detection/ips_context.cc @@ -125,6 +125,14 @@ void IpsContext::snapshot_flow(Flow* f) flow.proto_id = f->ssn_state.snort_protocol_id; } +void IpsContext::post_detection() +{ + for ( auto callback : post_callbacks ) + callback(this); + + post_callbacks.clear(); +} + //-------------------------------------------------------------------------- // unit tests //-------------------------------------------------------------------------- @@ -191,5 +199,25 @@ TEST_CASE("IpsContext basic", "[IpsContext]") } CHECK(TestData::count == num_data); } + +IpsContext* post_val; +void test_post(IpsContext* c) +{ post_val = c; } + +TEST_CASE("IpsContext post detection", "[IpsContext]") +{ + post_val = nullptr; + IpsContext c; + c.register_post_callback(test_post); + + CHECK( post_val == nullptr); + c.post_detection(); + CHECK( post_val == &c); + + // callbacks should be cleared + post_val = nullptr; + c.post_detection(); + CHECK( post_val == nullptr ); +} #endif diff --git a/src/detection/ips_context.h b/src/detection/ips_context.h index 86031c099..519c6401a 100644 --- a/src/detection/ips_context.h +++ b/src/detection/ips_context.h @@ -67,6 +67,8 @@ protected: class SO_PUBLIC IpsContext { public: + using Callback = void(*)(IpsContext*); + IpsContext(unsigned size = 0); // defaults to max id ~IpsContext(); @@ -94,6 +96,14 @@ public: enum ActiveRules { NONE, NON_CONTENT, CONTENT }; + void register_post_callback(Callback callback) + { post_callbacks.push_back(callback); } + + void clear_callbacks() + { post_callbacks.clear(); } + + void post_detection(); + public: Packet* packet; Packet* encode_packet; @@ -120,6 +130,8 @@ public: private: FlowSnapshot flow; std::vector data; + std::vector post_callbacks; + unsigned slot; }; } diff --git a/src/detection/regex_offload.cc b/src/detection/regex_offload.cc index 57986b52b..9e34e056d 100644 --- a/src/detection/regex_offload.cc +++ b/src/detection/regex_offload.cc @@ -146,7 +146,9 @@ void RegexOffload::put(unsigned id, snort::Packet* p) bool RegexOffload::get(unsigned& id) { assert(!busy.empty()); - RegexRequest* req = busy.front(); // FIXIT-H onload any order + + // FIXIT-H onload flows in any order + RegexRequest* req = busy.front(); if ( req->offload ) return false; diff --git a/src/flow/flow.cc b/src/flow/flow.cc index 5e8344c5c..ab524bc7f 100644 --- a/src/flow/flow.cc +++ b/src/flow/flow.cc @@ -170,6 +170,8 @@ void Flow::reset(bool do_cleanup) constexpr size_t offset = offsetof(Flow, flow_data); // FIXIT-L need a struct to zero here to make future proof memset((uint8_t*)this+offset, 0, sizeof(Flow)-offset); + + de.get_context()->clear_callbacks(); } void Flow::restart(bool dump_flow_data) diff --git a/src/stream/tcp/segment_overlap_editor.h b/src/stream/tcp/segment_overlap_editor.h index a0b25d7d1..89b802c87 100644 --- a/src/stream/tcp/segment_overlap_editor.h +++ b/src/stream/tcp/segment_overlap_editor.h @@ -76,6 +76,7 @@ struct TcpReassemblerState { SegmentOverlapState sos; TcpStreamTracker* tracker; + snort::Packet* last_pdu = nullptr; uint32_t flush_count; // number of flushed queued segments uint32_t xtradata_mask; // extra data available to log bool server_side; diff --git a/src/stream/tcp/tcp_reassembler.cc b/src/stream/tcp/tcp_reassembler.cc index 64cc1c598..a79d4f80f 100644 --- a/src/stream/tcp/tcp_reassembler.cc +++ b/src/stream/tcp/tcp_reassembler.cc @@ -38,6 +38,28 @@ using namespace snort; +static THREAD_LOCAL Packet* last_pdu = nullptr; + +void purge_alerts_callback_ackd(IpsContext* c) +{ + TcpSession* session = (TcpSession*)c->packet->flow->session; + + if ( c->packet->is_from_server() ) + session->client.reassembler.purge_alerts(); + else + session->server.reassembler.purge_alerts(); +} + +void purge_alerts_callback_ips(IpsContext* c) +{ + TcpSession* session = (TcpSession*)c->packet->flow->session; + + if ( c->packet->is_from_server() ) + session->server.reassembler.purge_alerts(); + else + session->client.reassembler.purge_alerts(); +} + void TcpReassembler::trace_segments(TcpReassemblerState& trs) { TcpSegmentNode* tsn = trs.sos.seglist.head; @@ -224,16 +246,17 @@ int TcpReassembler::dup_reassembly_segment( return STREAM_INSERT_OK; } -int TcpReassembler::purge_alerts(TcpReassemblerState& trs, Flow* flow) +void TcpReassembler::purge_alerts(TcpReassemblerState& trs) { + Flow* flow = trs.sos.session->flow; + for (int i = 0; i < trs.tracker->alert_count; i++) { StreamAlertInfo* ai = trs.tracker->alerts + i; Stream::log_extra_data(flow, trs.xtradata_mask, ai->event_id, ai->event_second); } trs.tracker->alert_count = 0; - - return 0; + last_pdu = nullptr; } int TcpReassembler::purge_to_seq(TcpReassemblerState& trs, uint32_t flush_seq) @@ -266,7 +289,17 @@ int TcpReassembler::purge_to_seq(TcpReassemblerState& trs, uint32_t flush_seq) if ( SEQ_LT(trs.tracker->rcv_nxt, flush_seq) ) trs.tracker->rcv_nxt = flush_seq; - purge_alerts(trs, trs.sos.session->flow); + if ( last_pdu ) + { + if ( trs.tracker->normalizer.is_tcp_ips_enabled() ) + last_pdu->context->register_post_callback(purge_alerts_callback_ips); + else + last_pdu->context->register_post_callback(purge_alerts_callback_ackd); + + last_pdu = nullptr; + } + else + purge_alerts(trs); if ( trs.sos.seglist.head == nullptr ) trs.sos.seglist.tail = nullptr; @@ -561,6 +594,9 @@ int TcpReassembler::_flush_to_seq( NoProfile exclude(s5TcpFlushPerfStats); Snort::inspect(pdu); + + if ( pdu->flow->is_offloaded() ) + last_pdu = pdu; } else { diff --git a/src/stream/tcp/tcp_reassembler.h b/src/stream/tcp/tcp_reassembler.h index b66e8d78f..68283de92 100644 --- a/src/stream/tcp/tcp_reassembler.h +++ b/src/stream/tcp/tcp_reassembler.h @@ -42,6 +42,7 @@ public: virtual int flush_on_data_policy(TcpReassemblerState&, snort::Packet*); virtual int flush_on_ack_policy(TcpReassemblerState&, snort::Packet*); virtual void trace_segments(TcpReassemblerState&); + virtual void purge_alerts(TcpReassemblerState&); protected: TcpReassembler() = default; @@ -61,7 +62,6 @@ protected: void queue_reassembly_segment(TcpReassemblerState&, TcpSegmentNode* prev, TcpSegmentNode*); void init_overlap_editor(TcpReassemblerState&, TcpSegmentDescriptor&); bool is_segment_fasttrack(TcpReassemblerState&, TcpSegmentNode* tail, TcpSegmentDescriptor&); - int purge_alerts(TcpReassemblerState&, snort::Flow*); void show_rebuilt_packet(TcpReassemblerState&, snort::Packet*); uint32_t get_flush_data_len( TcpReassemblerState&, TcpSegmentNode*, uint32_t to_seq, unsigned max); diff --git a/src/stream/tcp/tcp_reassemblers.h b/src/stream/tcp/tcp_reassemblers.h index affa5ba98..895cb8c33 100644 --- a/src/stream/tcp/tcp_reassemblers.h +++ b/src/stream/tcp/tcp_reassemblers.h @@ -43,6 +43,9 @@ public: int queue_packet_for_reassembly(TcpSegmentDescriptor& tsd) { return reassembler->queue_packet_for_reassembly(trs, tsd); } + void purge_alerts() + { reassembler->purge_alerts(trs); } + void purge_segment_list() { reassembler->purge_segment_list(trs); }