]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #2647 in SNORT/snort3 from ~RDEMPSTE/snort3:removed_inspectors...
authorRon Dempster (rdempste) <rdempste@cisco.com>
Wed, 9 Dec 2020 17:30:29 +0000 (17:30 +0000)
committerRon Dempster (rdempste) <rdempste@cisco.com>
Wed, 9 Dec 2020 17:30:29 +0000 (17:30 +0000)
Squashed commit of the following:

commit 7225fb279cd1e10e52599be338717df86035b943
Author: Ron Dempster (rdempste) <rdempste@cisco.com>
Date:   Tue Dec 8 08:00:54 2020 -0500

    packet_tracer: Fix the debug session information for non-ip packets

commit d9a1d78c903830f71fbe33dc834912204e7f6579
Author: Ron Dempster (rdempste) <rdempste@cisco.com>
Date:   Wed Dec 2 11:52:54 2020 -0500

    stream: fix stream clean up when going from enabled to disabled

commit 5e6d47c4f4b8370769bb30a88e706ceccb5899ba
Author: Ron Dempster (rdempste) <rdempste@cisco.com>
Date:   Wed Nov 25 13:51:08 2020 -0500

    managers: don't allow a referenced inspector to stall emptying the trash

commit 1843e30d47f5083a2d84f0061ba56d97dd2b0fe7
Author: Ron Dempster (rdempste) <rdempste@cisco.com>
Date:   Sat Dec 5 08:02:49 2020 -0500

    managers: track removed inspectors during reload and call tear_down and tterm to release resources

17 files changed:
src/framework/inspector.h
src/main.cc
src/main/analyzer.cc
src/main/analyzer.h
src/main/analyzer_command.cc
src/main/snort.cc
src/main/snort.h
src/main/swapper.cc
src/main/swapper.h
src/main/test/stubs.h
src/managers/inspector_manager.cc
src/managers/inspector_manager.h
src/network_inspectors/packet_tracer/packet_tracer.cc
src/stream/base/stream_base.cc
src/stream/base/stream_module.cc
src/stream/base/stream_module.h
src/stream/tcp/tcp_segment_descriptor.cc

index 9641c3806744d2f51732f98c28519f7f89eb464f..6417785319eb98122bfb35284140da6c11b8c0da 100644 (file)
@@ -72,6 +72,12 @@ public:
     // return verification status
     virtual bool configure(SnortConfig*) { return true; }
 
+    // cleanup for inspector instance removal from the running configuration
+    // this is only called for inspectors in the default inspection policy that
+    // were present in the prior snort configuration and were removed in the snort
+    // configuration that is being loaded during a reload_config command
+    virtual void tear_down(SnortConfig*) { }
+
     // called on controls after everything is configured
     // return true if there is nothing to do ever based on config
     virtual bool disable(SnortConfig*) { return false; }
index 12506f74539dc20225528adbbf089f874307d37c..9b044399a2aa5109452b178c7e5ac7faa43fc937 100644 (file)
@@ -353,7 +353,7 @@ int main_reload_config(lua_State* L)
 
     current_request->respond(".. reloading configuration\n");
     const SnortConfig* old = SnortConfig::get_conf();
-    SnortConfig* sc = Snort::get_reload_config(fname, plugin_path);
+    SnortConfig* sc = Snort::get_reload_config(fname, plugin_path, old);
 
     if ( !sc )
     {
index b90d418dc27498264a91123d1ba923bfacc31f1e..fc7a8de596675352251d54fd6ed31c9a14b98f7d 100644 (file)
@@ -597,6 +597,11 @@ void Analyzer::reinit(const SnortConfig* sc)
     TraceApi::thread_reinit(sc->trace_config);
 }
 
+void Analyzer::stop_removed(const SnortConfig* sc)
+{
+    InspectorManager::thread_stop_removed(sc);
+}
+
 void Analyzer::term()
 {
     const SnortConfig* sc = SnortConfig::get_conf();
index 01f4111f4462ec51c71837aacdab5ee221950e6a..bb2f1340ad133ee13062a4e2ee105aa978803839 100644 (file)
@@ -105,6 +105,7 @@ public:
     void resume(uint64_t msg_cnt);
     void reload_daq();
     void reinit(const snort::SnortConfig*);
+    void stop_removed(const snort::SnortConfig*);
     void rotate();
     snort::SFDAQInstance* get_daq_instance() { return daq_instance; }
 
index ea2a509807b9b5d36088caf570c4ad4d88a6b13d..64cfe2438d98d7dea0a312acb8f557f0ba92c022 100644 (file)
@@ -146,6 +146,7 @@ bool ACSwap::execute(Analyzer& analyzer, void** ac_state)
             if ( reload_tuners->empty() )
             {
                 delete reload_tuners;
+                ps->finish(analyzer);
                 return true;
             }
 
index f5c3da1fa44b07a646baeea2b393903e7e73b888..30647d1894103a27fd25ed6803f64fa20a7fe4cb 100644 (file)
@@ -447,7 +447,8 @@ void Snort::reload_failure_cleanup(SnortConfig* sc)
 
 // FIXIT-M refactor this so startup and reload call the same core function to
 // instantiate things that can be reloaded
-SnortConfig* Snort::get_reload_config(const char* fname, const char* plugin_path)
+SnortConfig* Snort::get_reload_config(const char* fname, const char* plugin_path,
+    const SnortConfig* old)
 {
     reloading = true;
     ModuleManager::reset_errors();
@@ -477,6 +478,7 @@ SnortConfig* Snort::get_reload_config(const char* fname, const char* plugin_path
         return nullptr;
     }
 
+    InspectorManager::tear_down_removed_inspectors(old, sc);
     InspectorManager::prepare_controls(sc);
 
     FileService::verify_reload(sc);
index 82c930e9983826c1812edc61ce7d2770058a3d78..c6eee51fdb30221fe6b2ecd80475cb991f8a47b1 100644 (file)
@@ -38,7 +38,8 @@ struct SnortConfig;
 class Snort
 {
 public:
-    static SnortConfig* get_reload_config(const char* fname, const char* plugin_path = nullptr);
+    static SnortConfig* get_reload_config(const char* fname, const char* plugin_path,
+        const SnortConfig* old);
     static SnortConfig* get_updated_policy(SnortConfig*, const char* fname, const char* iname);
     static SnortConfig* get_updated_module(SnortConfig*, const char* name);
     static void setup(int argc, char* argv[]);
index 39f6a09a7b9941999d470661bf397306d087298c..68777ede54987e219215d48ed7a7eb8f51d2c4ca 100644 (file)
@@ -23,6 +23,8 @@
 
 #include "swapper.h"
 
+#include "managers/inspector_manager.h"
+
 #include "analyzer.h"
 #include "snort.h"
 #include "snort_config.h"
@@ -51,6 +53,8 @@ Swapper::Swapper()
 
 Swapper::~Swapper()
 {
+    if ( new_conf )
+        InspectorManager::clear_removed_inspectors(new_conf);
     if ( old_conf )
         delete old_conf;
 }
@@ -66,3 +70,9 @@ void Swapper::apply(Analyzer& analyzer)
             analyzer.reinit(new_conf);
     }
 }
+
+void Swapper::finish(Analyzer& analyzer)
+{
+    if ( new_conf )
+        analyzer.stop_removed(new_conf);
+}
index 4defaaf8e19ed37d38a29c65cd61751780847b43..78ce49b90becd0d2ed9c59a83a0576f8fee3afc6 100644 (file)
@@ -40,6 +40,7 @@ public:
     ~Swapper();
 
     void apply(Analyzer&);
+    void finish(Analyzer&);
     snort::SnortConfig* get_new_conf() { return new_conf; }
 
     static bool get_reload_in_progress() { return reload_in_progress; }
index 5405b56ba05b0603dc56a28d93349d8d19de91e0..703f4e6e6cdf77c51105b2af6f9d295d33977984 100644 (file)
@@ -200,6 +200,7 @@ void InspectorManager::thread_init(const SnortConfig*) { }
 void InspectorManager::thread_term() { }
 void InspectorManager::thread_stop(const SnortConfig*) { }
 void InspectorManager::thread_reinit(const SnortConfig*) { }
+void InspectorManager::thread_stop_removed(const SnortConfig*) { }
 void ModuleManager::accumulate() { }
 void Stream::handle_timeouts(bool) { }
 void Stream::purge_flows() { }
index bcb164d920fce7f9cdb2dc58bcdc77189815e55c..a17c7681078ce15154251e2b6457ff875d4b95fa 100644 (file)
@@ -218,6 +218,7 @@ void PHVector::add_control(PHInstance* p)
 struct FrameworkPolicy
 {
     PHInstanceList ilist;   // List of inspector module instances
+    PHInstanceList removed_ilist;   // List of removed inspector module instances
 
     PHVector passive;
     PHVector packet;
@@ -392,12 +393,15 @@ static void empty_trash(PHList& trash)
     while ( !trash.empty() )
     {
         auto* p = trash.front();
+        trash.pop_front();
 
         if ( !p->is_inactive() )
+        {
+            trash.emplace_back(p);
             return;
+        }
 
         InspectorManager::free_inspector(p);
-        trash.pop_front();
     }
 }
 
@@ -532,6 +536,31 @@ Binder* InspectorManager::get_binder()
     return (Binder*)pi->framework_policy->binder;
 }
 
+void InspectorManager::clear_removed_inspectors(SnortConfig* sc)
+{
+    FrameworkPolicy* fp = sc->policy_map->get_inspection_policy()->framework_policy;
+    for ( auto* p : fp->removed_ilist )
+        p->handler->rem_ref();
+    fp->removed_ilist.clear();
+}
+
+void InspectorManager::tear_down_removed_inspectors(const SnortConfig* old, SnortConfig* sc)
+{
+    FrameworkPolicy* fp = get_default_inspection_policy(sc)->framework_policy;
+    InspectionPolicy* old_p = get_default_inspection_policy(old);
+    FrameworkPolicy* old_fp = old_p->framework_policy;
+    for (auto it = old_fp->ilist.begin(); it != old_fp->ilist.end(); ++it)
+    {
+        PHInstance* instance = get_instance(fp, (*it)->name.c_str());
+        if (!instance)
+        {
+            fp->removed_ilist.emplace_back(*it);
+            (*it)->handler->add_ref();
+            (*it)->handler->tear_down(sc);
+        }
+    }
+}
+
 // FIXIT-P cache get_inspector() returns or provide indexed lookup
 Inspector* InspectorManager::get_inspector(const char* key, bool dflt_only, const SnortConfig* sc)
 {
@@ -728,6 +757,26 @@ void InspectorManager::thread_reinit(const SnortConfig* sc)
     }
 }
 
+void InspectorManager::thread_stop_removed(const SnortConfig* sc)
+{
+    // pin->tinit() only called for default policy
+    InspectionPolicy* pi = get_default_inspection_policy(sc);
+
+    if ( pi && pi->framework_policy )
+    {
+        // Call pin->tterm() for anything that has been initialized and removed
+        for ( auto* p : pi->framework_policy->removed_ilist )
+        {
+            PHGlobal& phg = get_thread_local_plugin(p->pp_class.api);
+            if ( phg.instance_initialized )
+            {
+                p->handler->tterm();
+                phg.instance_initialized = false;
+            }
+        }
+    }
+}
+
 void InspectorManager::thread_stop(const SnortConfig* sc)
 {
     // If thread_init() was never called, we have nothing to do.
@@ -738,10 +787,6 @@ void InspectorManager::thread_stop(const SnortConfig* sc)
     set_default_policy(sc);
     InspectionPolicy* pi = get_inspection_policy();
 
-    // FIXIT-RC Any inspectors that were once configured/instantiated but
-    // no longer exist in the conf cannot have their instance tterm()
-    // called and will leak!
-
     if ( pi && pi->framework_policy )
     {
         for ( auto* p : pi->framework_policy->ilist )
index 377dc1354ccc77a79c609a684187ad2b9c7ea5f6..dcc84724c3628f4edf1d9211aa5e5affc920555b 100644 (file)
@@ -77,6 +77,7 @@ public:
 
     static void thread_init(const SnortConfig*);
     static void thread_reinit(const SnortConfig*);
+    static void thread_stop_removed(const SnortConfig*);
 
     static void thread_stop(const SnortConfig*);
     static void thread_term();
@@ -88,6 +89,8 @@ public:
 
     static void clear(Packet*);
     static void empty_trash();
+    static void tear_down_removed_inspectors(const SnortConfig*, SnortConfig*);
+    static void clear_removed_inspectors(SnortConfig*);
 
 #ifdef PIGLET
     static Inspector* instantiate(const char*, Module*, SnortConfig*);
index dd28e5a29eee0600f62dbeca48da30f91c7fb629..258ddaf45a1ba0993facedfd44f351ffe5dd4f0e 100644 (file)
@@ -346,15 +346,37 @@ void PacketTracer::add_packet_type_info(const Packet& p)
 void PacketTracer::add_eth_header_info(const Packet& p)
 {
     auto eh = layer::get_eth_layer(&p);
-    if (!(shell_enabled) && eh )
+    if (eh)
     {
-        // MAC layer
-        PacketTracer::log("%02X:%02X:%02X:%02X:%02X:%02X -> %02X:%02X:%02X:%02X:%02X:%02X %04X\n",
-            eh->ether_src[0], eh->ether_src[1], eh->ether_src[2],
-            eh->ether_src[3], eh->ether_src[4], eh->ether_src[5],
-            eh->ether_dst[0], eh->ether_dst[1], eh->ether_dst[2],
-            eh->ether_dst[3], eh->ether_dst[4], eh->ether_dst[5],
-            (uint16_t)eh->ethertype());
+        if (shell_enabled)
+        {
+            PacketTracer::log("\n");
+            char gr_buf[32] = { '\0' };
+            if (p.is_inter_group_flow())
+                snprintf(gr_buf, sizeof(gr_buf), " GR=%hd-%hd", p.pkth->ingress_group,
+                    p.pkth->egress_group);
+
+            snprintf(debug_session, sizeof(debug_session),
+                "%02X:%02X:%02X:%02X:%02X:%02X -> %02X:%02X:%02X:%02X:%02X:%02X %04X"
+                " AS=%hu ID=%u%s ",
+                eh->ether_src[0], eh->ether_src[1], eh->ether_src[2],
+                eh->ether_src[3], eh->ether_src[4], eh->ether_src[5],
+                eh->ether_dst[0], eh->ether_dst[1], eh->ether_dst[2],
+                eh->ether_dst[3], eh->ether_dst[4], eh->ether_dst[5],
+                (uint16_t)eh->ethertype(), p.pkth->address_space_id, get_instance_id(),
+                gr_buf);
+            s_pkt_trace->active = true;
+        }
+        else
+        {
+            // MAC layer
+            PacketTracer::log("%02X:%02X:%02X:%02X:%02X:%02X -> %02X:%02X:%02X:%02X:%02X:%02X %04X\n",
+                eh->ether_src[0], eh->ether_src[1], eh->ether_src[2],
+                eh->ether_src[3], eh->ether_src[4], eh->ether_src[5],
+                eh->ether_dst[0], eh->ether_dst[1], eh->ether_dst[2],
+                eh->ether_dst[3], eh->ether_dst[4], eh->ether_dst[5],
+                (uint16_t)eh->ethertype());
+        }
     }
 }
 
index fe914be03c5fa4dc80ad1dcf1c75b913a1a48c86..2de2a211bf1acf97f990ede99f989e5bca60fa07 100644 (file)
@@ -156,6 +156,8 @@ public:
     StreamBase(const StreamModuleConfig*);
     void show(const SnortConfig*) const override;
 
+    void tear_down(SnortConfig*) override;
+
     void tinit() override;
     void tterm() override;
 
@@ -168,6 +170,9 @@ public:
 StreamBase::StreamBase(const StreamModuleConfig* c)
 { config = *c; }
 
+void StreamBase::tear_down(SnortConfig* sc)
+{ sc->register_reload_resource_tuner(new StreamUnloadReloadResourceManager); }
+
 void StreamBase::tinit()
 {
     assert(!flow_con && config.flow_cache_cfg.max_flows);
@@ -212,6 +217,9 @@ void StreamBase::tterm()
 {
     StreamHAManager::tterm();
     FlushBucket::clear();
+    base_prep();
+    delete flow_con;
+    flow_con = nullptr;
 }
 
 void StreamBase::show(const SnortConfig* sc) const
@@ -316,10 +324,6 @@ static void base_tterm()
 {
     StreamHAManager::tterm();
     FlushBucket::clear();
-
-    // this can't happen sooner because the counts haven't been harvested yet
-    delete flow_con;
-    flow_con = nullptr;
     TcpStreamTracker::thread_term();
 }
 
index 3157338f8a36beebbcdb33973ae159d15fbcb316..0bdbbb3693766211472799fa51237b525f9d4a07 100644 (file)
@@ -292,6 +292,44 @@ bool StreamReloadResourceManager::tune_resources(unsigned work_limit)
     return ( flows_to_delete ) ? false : true;
 }
 
+bool StreamUnloadReloadResourceManager::tinit()
+{
+    unsigned max_flows = flow_con->get_flow_cache_config().max_flows;
+    if (max_flows)
+    {
+        stream_base_stats.reload_total_deletes += max_flows;
+        return true;
+    }
+    return false;
+}
+
+bool StreamUnloadReloadResourceManager::tune_packet_context()
+{
+    ++stream_base_stats.reload_tuning_packets;
+    return tune_resources(max_work);
+}
+
+bool StreamUnloadReloadResourceManager::tune_idle_context()
+{
+    ++stream_base_stats.reload_tuning_idle;
+    return tune_resources(max_work_idle);
+}
+
+bool StreamUnloadReloadResourceManager::tune_resources(unsigned work_limit)
+{
+    unsigned flows_to_delete = flow_con->get_flows_allocated();
+
+    if (!flows_to_delete)
+        return true;
+
+    if (flows_to_delete > work_limit)
+        flows_to_delete -= flow_con->delete_flows(work_limit);
+    else
+        flows_to_delete -= flow_con->delete_flows(flows_to_delete);
+
+    return (flows_to_delete) ? false : true;
+}
+
 void StreamModuleConfig::show() const
 {
     ConfigLogger::log_value("max_flows", flow_cache_cfg.max_flows);
index fcf54c1a43ca7b1b99810f35a7e4cbea622d3bd7..a789bc5a0279c295ac0ecbfc2fade9a8444bbfda 100644 (file)
@@ -117,6 +117,19 @@ private:
     timeval reload_time{};
 };
 
+class StreamUnloadReloadResourceManager : public snort::ReloadResourceTuner
+{
+public:
+    StreamUnloadReloadResourceManager() { }
+
+    bool tinit() override;
+    bool tune_packet_context() override;
+    bool tune_idle_context() override;
+
+private:
+    bool tune_resources(unsigned work_limit);
+};
+
 class StreamModule : public snort::Module
 {
 public:
index 8b0ee0b66f3541dd0e842789660dc835699ae0b9..4dc188b243ccc26c4975b3c4a29880dc07b9ccf5 100644 (file)
@@ -97,7 +97,10 @@ void TcpSegmentDescriptor::setup()
 { ma_pseudo_packet = new Packet(false); }
 
 void TcpSegmentDescriptor::clear()
-{ delete ma_pseudo_packet; }
+{
+    delete ma_pseudo_packet;
+    ma_pseudo_packet = nullptr;
+}
 
 uint32_t TcpSegmentDescriptor::init_mss(uint16_t* value)
 {