]> git.ipfire.org Git - thirdparty/snort3.git/commitdiff
Merge pull request #1446 in SNORT/snort3 from ~SBAIGAL/snort3:reload_ips_action to...
authorTom Peters (thopeter) <thopeter@cisco.com>
Mon, 3 Dec 2018 20:51:10 +0000 (15:51 -0500)
committerTom Peters (thopeter) <thopeter@cisco.com>
Mon, 3 Dec 2018 20:51:10 +0000 (15:51 -0500)
Squashed commit of the following:

commit 074dfc4ae15200a97300469818c3adc166a9b2ee
Author: Steven Baigal <sbaigal@cisco.com>
Date:   Tue Nov 27 14:00:50 2018 -0500

    reload action: updated action manager to support reload

12 files changed:
src/detection/fp_detect.cc
src/detection/fp_detect.h
src/ips_options/asn1_util.cc
src/main/modules.cc
src/main/snort.cc
src/main/snort.h
src/main/snort_config.cc
src/main/snort_config.h
src/main/swapper.cc
src/managers/action_manager.cc
src/managers/action_manager.h
src/packet_io/active.cc

index 6b7a09eee396105635ff67c8c9c477bf0a3510f6..b89b1fc364c18c38ffbb4a29a60f50ee7fce6ae7 100644 (file)
@@ -226,7 +226,7 @@ int fpLogEvent(const RuleTreeNode* rtn, const OptTreeNode* otn, Packet* p)
 
 /*
 **  DESCRIPTION
-**    Add and Event to the appropriate Match Queue: Alert, Pass, or Log.
+**    Add an Event to the appropriate Match Queue: Alert, Pass, or Log.
 **    This allows us to find multiple events per packet and pick the 'best'
 **    one.  This function also allows us to change the order of alert,
 **    pass, and log signatures by caching them for decision later.
@@ -832,10 +832,11 @@ void fp_set_context(IpsContext& c)
     c.stash = new MpseStash;
 
     c.otnx = (OtnxMatchData*)snort_calloc(sizeof(OtnxMatchData));
-    c.otnx->iMatchInfoArraySize = SnortConfig::get_conf()->num_rule_types;
+    // FIXIT-L use dynamic array size from configure, resize it when reload
+    c.otnx->iMatchInfoArraySize = (MAX_NUM_RULE_TYPES * 2);
 
     c.otnx->matchInfo = (MatchInfo*)snort_calloc(
-        SnortConfig::get_conf()->num_rule_types, sizeof(MatchInfo));
+        c.otnx->iMatchInfoArraySize, sizeof(MatchInfo));
 
     c.context_num = 0;
 }
index 348dbe265924d1188c8ef6ba6a8e4487230d7152..ff9d00dd05bfc506103741a1fbaef10b925ae97d 100644 (file)
@@ -51,6 +51,8 @@ struct RuleTreeNode;
 int fpLogEvent(const RuleTreeNode*, const OptTreeNode*, snort::Packet*);
 int fpEvalRTN(RuleTreeNode*, snort::Packet*, int check_ports);
 
+#define MAX_NUM_RULE_TYPES 10   // max number of known rule types
+
 /*
 **  This define is for the number of unique events
 **  to match before choosing which event to log.
index 582413ea32a84decd0dfa4b1babdf391f60a6b31..eb0cc1d07bcc167f6aace1d4f5c4ff1c7c43454e 100644 (file)
@@ -109,26 +109,15 @@ static ASN1_TYPE* asn1_node_alloc()
 **  an ASN.1 decode.  Pass in the max number of nodes for an ASN.1 decode and
 **  we will track that many.
 **
-**  @return integer
+**  @return none
 **
-**  @retval ASN1_OK function successful
-**  @retval ASN1_ERR_MEM_ALLOC memory allocation failed
-**  @retval ASN1_ERR_INVALID_ARG invalid argument
 */
 void asn1_init_mem(snort::SnortConfig* sc)
 {
-    int num_nodes;
-
-    if (sc->asn1_mem != 0)
-        num_nodes = sc->asn1_mem;
-    else
-        num_nodes = 256;
-
-    if (num_nodes <= 0)
-        return;
+    asn1_config.num_nodes = sc->asn1_mem;
 
-    asn1_config.mem = (ASN1_TYPE*)snort_calloc(num_nodes, sizeof(ASN1_TYPE));
-    asn1_config.num_nodes = num_nodes;
+    if (asn1_config.num_nodes > 0)
+        asn1_config.mem = (ASN1_TYPE*)snort_calloc(asn1_config.num_nodes, sizeof(ASN1_TYPE));
     node_index = 0;
 }
 
index 2537005106112605975e5fcec63e03c40f2b597e..5fb9a1c341470b9c7887dae611ff392ee5ac9984 100755 (executable)
@@ -69,7 +69,7 @@ using namespace std;
 /* *INDENT-OFF* */   //  Uncrustify handles this section incorrectly.
 static const Parameter detection_params[] =
 {
-    { "asn1", Parameter::PT_INT, "1:", "256",
+    { "asn1", Parameter::PT_INT, "0:256", "0",
       "maximum decode nodes" },
 
     { "offload_limit", Parameter::PT_INT, "0:", "99999",
index 0c954983c30a2fde53aacc735711552f54f1c3b3..7841fc7e8f77f05d918006530098e26bdd0a9e44 100644 (file)
@@ -832,6 +832,12 @@ void Snort::thread_init_unprivileged()
     PacketManager::thread_init();
 }
 
+void Snort::thread_reinit(SnortConfig* sc)
+{
+    InspectorManager::thread_reinit(sc);
+    ActionManager::thread_reinit(sc);
+}
+
 void Snort::thread_term()
 {
     HighAvailabilityManager::thread_term_beginning();
index d5aad8b408f2dfadc2fef9b7e30af3a0eaea8a72..be543679d00bb21a6bf002ce40031c290d250518 100644 (file)
@@ -66,6 +66,7 @@ public:
 
     static bool thread_init_privileged(const char* intf);
     static void thread_init_unprivileged();
+    static void thread_reinit(SnortConfig*);
     static void thread_term();
 
     static void thread_idle();
index 158627d602f6e14683fd8d313ed3afe110008d53..4423ba06a3f2ddad4f69774b94164f5d077004af 100644 (file)
@@ -40,6 +40,7 @@
 #include "ips_options/ips_flowbits.h"
 #include "latency/latency_config.h"
 #include "log/messages.h"
+#include "managers/action_manager.h"
 #include "managers/event_manager.h"
 #include "managers/inspector_manager.h"
 #include "managers/ips_manager.h"
@@ -189,6 +190,7 @@ void SnortConfig::init(const SnortConfig* const other_conf, ProtocolReference* p
         mpls_stack_depth = DEFAULT_LABELCHAIN_LENGTH;
 
         daq_config = new SFDAQConfig();
+        ActionManager::new_config(this);
         InspectorManager::new_config(this);
 
         num_slots = ThreadConfig::get_instance_max();
@@ -293,6 +295,7 @@ SnortConfig::~SnortConfig()
 
     delete policy_map;
     InspectorManager::delete_config(this);
+    ActionManager::delete_config(this);
 
     delete[] state;
     delete thread_config;
index cec6857539f3ba7c5b729c5363c282c01239ff23..861f1de7906d4e759aa96ded9a710e5369067a8f 100644 (file)
@@ -128,6 +128,7 @@ struct RulePortTables;
 struct RuleState;
 struct DetectionFilterConfig;
 struct EventQueueConfig;
+struct IpsActionsConfig;
 class FastPatternConfig;
 struct FrameworkConfig;
 struct ThresholdConfig;
@@ -314,6 +315,7 @@ public:
     RuleListNode* rule_lists = nullptr;
     int evalOrder[Actions::MAX + 1];
 
+    IpsActionsConfig* ips_actions_config = nullptr;
     FrameworkConfig* framework_config = nullptr;
 
     /* master port list table */
@@ -355,7 +357,6 @@ public:
     ProfilerConfig* profiler = nullptr;
 
     LatencyConfig* latency = nullptr;
-    _IntelPmHandles* ipm_handles = nullptr;
 
     unsigned remote_control_port = 0;
     std::string remote_control_socket;
index ebed3b7270d5ba6350035c0ed1cb76016cf75f47..0e05f76dacacb9680a8d2cc95c86d9262d27a31b 100644 (file)
@@ -23,9 +23,9 @@
 
 #include "swapper.h"
 
-#include "managers/inspector_manager.h"
 #include "target_based/sftarget_reader.h"
 
+#include "snort.h"
 #include "snort_config.h"
 
 using namespace snort;
@@ -83,8 +83,9 @@ void Swapper::apply()
     {
         const bool reload = (snort::SnortConfig::get_conf() != nullptr);
         snort::SnortConfig::set_conf(new_conf);
+        // FIXIT-M Determine whether we really want to do this before or after the set_conf
         if (reload)
-            snort::InspectorManager::thread_reinit(new_conf);
+            snort::Snort::thread_reinit(new_conf);
     }
 
     if ( new_attribs )
index 4bd79a52a7b35a165b25bb648b1c6b6f4cb5dbce..82ca0c683c21e5cc0400219ad09f7ff9deaf0741 100644 (file)
 
 #include "action_manager.h"
 
-#include <list>
+#include <vector>
 
 #include "actions/act_replace.h"
 #include "log/messages.h"
+#include "main/snort_config.h"
 #include "packet_io/active.h"
 #include "parser/parser.h"
 
 using namespace snort;
 using namespace std;
 
-struct Actor
+struct ActionClass
 {
     const ActionApi* api;
+    bool initialized = false;   // In the context of the main thread, this means that api.pinit()
+                                // has been called.  In the packet thread, it means that api.tinit()
+                                // has been called.
+
+    ActionClass(const ActionApi* p) : api(p) { }
+};
+
+struct ActionInst
+{
+    ActionClass& cls;
     IpsAction* act;
 
-    Actor(const ActionApi* p)
-    { api = p; act = nullptr; }
+    ActionInst(ActionClass& cls, IpsAction* act) : cls(cls), act(act) { }
 };
 
-typedef list<Actor> AList;
-static AList s_actors;
+struct IpsActionsConfig
+{
+    vector<ActionInst> clist;
+    IpsAction* reject = nullptr;
+};
+
+typedef vector<ActionClass> ACList;
 
-static IpsAction* s_reject = nullptr;
-static THREAD_LOCAL IpsAction* s_action = nullptr;
+static ACList s_actors;
+
+static THREAD_LOCAL ACList* s_tl_actors = nullptr;
+static THREAD_LOCAL IpsAction* s_tl_action = nullptr;
 
 //-------------------------------------------------------------------------
-// action plugins
+// Main thread operations
 //-------------------------------------------------------------------------
 
+// Plugin/Class operations
 void ActionManager::add_plugin(const ActionApi* api)
 {
-    Actor a(api);
-
-    if ( api->pinit )
-        api->pinit();
-
-    s_actors.emplace_back(a);
+    s_actors.emplace_back(api);
 }
 
-void ActionManager::release_plugins()
+Actions::Type ActionManager::get_action_type(const char* s)
 {
     for ( auto& p : s_actors )
     {
-        p.api->dtor(p.act);
-
-        if ( p.api->pterm )
-            p.api->pterm();
+        if ( !strcmp(p.api->base.name, s) )
+            return p.api->type;
     }
-    s_actors.clear();
+    return Actions::NONE;
 }
 
 void ActionManager::dump_plugins()
@@ -82,85 +93,162 @@ void ActionManager::dump_plugins()
         d.dump(p.api->base.name, p.api->base.version);
 }
 
-static void store(const ActionApi* api, IpsAction* act)
+void ActionManager::release_plugins()
 {
     for ( auto& p : s_actors )
-        if ( p.api == api )
+    {
+        if ( p.api->pterm )
+            p.api->pterm();
+    }
+    s_actors.clear();
+}
+
+static ActionClass* get_action_class(const ActionApi* api, IpsActionsConfig* iac)
+{
+    for ( auto& ai : iac->clist )
+    {
+        if ( ai.cls.api == api )
+            return &ai.cls;
+    }
+
+    for ( auto& ac : s_actors )
+    {
+        if ( ac.api == api )
         {
-            //assert(!p.act);  FIXIT-RC memory leak on reload; move to SnortConfig?
-            p.act = act;
-            break;
+            if ( !ac.initialized )
+            {
+                if ( ac.api->pinit )
+                    ac.api->pinit();
+                ac.initialized = true;
+            }
+            return &ac;
         }
+    }
+
+    return nullptr;
 }
 
-//-------------------------------------------------------------------------
+// Config operations
+void ActionManager::new_config(SnortConfig* sc)
+{
+    sc->ips_actions_config = new IpsActionsConfig;
+}
 
-Actions::Type ActionManager::get_action_type(const char* s)
+void ActionManager::delete_config(SnortConfig* sc)
 {
-    for ( auto& p : s_actors )
-    {
-        if ( !strcmp(p.api->base.name, s) )
-            return p.api->type;
-    }
-    return Actions::NONE;
+    if (!sc->ips_actions_config)
+        return;
+
+    // Delete all IPS action instances that were created as part of this configuration
+    for (auto& ia : sc->ips_actions_config->clist)
+        ia.cls.api->dtor(ia.act);
+
+    delete sc->ips_actions_config;
+    sc->ips_actions_config = nullptr;
 }
 
-void ActionManager::instantiate(
-    const ActionApi* api, Module* m, SnortConfig* sc)
+void ActionManager::instantiate(const ActionApi* api, Module* mod, SnortConfig* sc)
 {
-    IpsAction* act = api->ctor(m);
+    ActionClass* cls = get_action_class(api, sc->ips_actions_config);
+    assert(cls != nullptr);
+
+    IpsAction* act = cls->api->ctor(mod);
 
     if ( act )
     {
-        if ( !s_reject && !strcmp(act->get_name(), "reject") )
-            s_reject = act;
+        // Add this instance to the list of those created for this config
+        sc->ips_actions_config->clist.emplace_back(*cls, act);
+
+        // FIXIT-M Either you are static or you're not, make a choice.
+        // Anyway, if we happen to instantiate an action called reject, cache that for use later.
+        if ( !sc->ips_actions_config->reject && !strcmp(act->get_name(), "reject") )
+            sc->ips_actions_config->reject = act;
 
         ListHead* lh = CreateRuleType(sc, api->base.name, api->type);
         assert(lh);
         lh->action = act;
+    }
+}
 
-        store(api, act);
+//-------------------------------------------------------------------------
+// Packet thread operations
+//-------------------------------------------------------------------------
+static ActionClass& get_thread_local_action_class(const ActionApi* api)
+{
+    for ( ActionClass& p : *s_tl_actors )
+    {
+        if ( p.api == api )
+            return p;
     }
+    s_tl_actors->emplace_back(api);
+    return s_tl_actors->back();
 }
 
-void ActionManager::thread_init(SnortConfig*)
+void ActionManager::thread_init(SnortConfig* sc)
 {
-    for ( auto& p : s_actors )
-        if ( p.api->tinit )
-            p.api->tinit();
+    // Initial build out of this thread's configured plugin registry
+    s_tl_actors = new ACList;
+    for ( auto& p : sc->ips_actions_config->clist )
+    {
+        ActionClass& tlac = get_thread_local_action_class(p.cls.api);
+        if ( tlac.api->tinit )
+            tlac.api->tinit();
+        tlac.initialized = true;
+    }
+}
+
+void ActionManager::thread_reinit(SnortConfig* sc)
+{
+    // Update this thread's configured plugin registry with any newly configured inspectors
+    for ( auto& p : sc->ips_actions_config->clist )
+    {
+        ActionClass& tlac = get_thread_local_action_class(p.cls.api);
+        if (!tlac.initialized)
+        {
+            if ( tlac.api->tinit )
+                tlac.api->tinit();
+            tlac.initialized = true;
+        }
+    }
+    Active::thread_init(sc);
 }
 
 void ActionManager::thread_term(SnortConfig*)
 {
-    for ( auto& p : s_actors )
+    // Call tterm for every IPS action plugin ever configured during the lifetime of this thread
+    for ( auto& p : *s_tl_actors )
+    {
         if ( p.api->tterm )
             p.api->tterm();
+    }
+    delete s_tl_actors;
+    s_tl_actors = nullptr;
 }
 
 void ActionManager::execute(Packet* p)
 {
-    if ( s_action )
+    if ( s_tl_action )
     {
-        s_action->exec(p);
-        s_action = nullptr;
+        s_tl_action->exec(p);
+        s_tl_action = nullptr;
     }
 }
 
 void ActionManager::queue(IpsAction* a)
 {
-    if ( !s_action || a->get_action() > s_action->get_action() )
-        s_action = a;
+    if ( !s_tl_action || a->get_action() > s_tl_action->get_action() )
+        s_tl_action = a;
 }
 
-void ActionManager::queue_reject()
+void ActionManager::queue_reject(SnortConfig* sc)
 {
-    if ( s_reject )
-        queue(s_reject);
+    if ( sc->ips_actions_config->reject )
+        queue(sc->ips_actions_config->reject);
 }
 
 void ActionManager::reset_queue()
 {
-    s_action = nullptr;
+    s_tl_action = nullptr;
     Replace_ResetQueue();
 }
 
index c9af1bddc246ba149d2fc05b8b675f5e087ad59e..774fe50033b65b222ef18593db30736b7255de30 100644 (file)
@@ -62,15 +62,18 @@ public:
     static void release_plugins();
     static void dump_plugins();
 
+    static void new_config(snort::SnortConfig*);
     static snort::Actions::Type get_action_type(const char*);
+    static void delete_config(snort::SnortConfig*);
 
     static void instantiate(const snort::ActionApi*, snort::Module*, snort::SnortConfig*);
 
     static void thread_init(snort::SnortConfig*);
+    static void thread_reinit(snort::SnortConfig*);
     static void thread_term(snort::SnortConfig*);
 
     static void reset_queue();
-    static void queue_reject();
+    static void queue_reject(snort::SnortConfig*);
     static void queue(snort::IpsAction*);
     static void execute(snort::Packet*);
 
index 27e34874fb78bdb1479e6ea64c48e28e5f3e56cc..cadbcde16ebb928e40281f4083b5f27f7597c0ea 100644 (file)
@@ -470,7 +470,7 @@ void Active::reset_session(Packet* p, bool force)
 
     if ( enabled )
     {
-        ActionManager::queue_reject();
+        ActionManager::queue_reject(SnortConfig::get_conf());
 
         if ( p->flow )
         {