From: Tom Peters (thopeter) Date: Mon, 3 Dec 2018 20:51:10 +0000 (-0500) Subject: Merge pull request #1446 in SNORT/snort3 from ~SBAIGAL/snort3:reload_ips_action to... X-Git-Tag: 3.0.0-250~7 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5247ce790e72058fdad340f19791252b2274f7a0;p=thirdparty%2Fsnort3.git Merge pull request #1446 in SNORT/snort3 from ~SBAIGAL/snort3:reload_ips_action to master Squashed commit of the following: commit 074dfc4ae15200a97300469818c3adc166a9b2ee Author: Steven Baigal Date: Tue Nov 27 14:00:50 2018 -0500 reload action: updated action manager to support reload --- diff --git a/src/detection/fp_detect.cc b/src/detection/fp_detect.cc index 6b7a09eee..b89b1fc36 100644 --- a/src/detection/fp_detect.cc +++ b/src/detection/fp_detect.cc @@ -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; } diff --git a/src/detection/fp_detect.h b/src/detection/fp_detect.h index 348dbe265..ff9d00dd0 100644 --- a/src/detection/fp_detect.h +++ b/src/detection/fp_detect.h @@ -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. diff --git a/src/ips_options/asn1_util.cc b/src/ips_options/asn1_util.cc index 582413ea3..eb0cc1d07 100644 --- a/src/ips_options/asn1_util.cc +++ b/src/ips_options/asn1_util.cc @@ -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; } diff --git a/src/main/modules.cc b/src/main/modules.cc index 253700510..5fb9a1c34 100755 --- a/src/main/modules.cc +++ b/src/main/modules.cc @@ -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", diff --git a/src/main/snort.cc b/src/main/snort.cc index 0c954983c..7841fc7e8 100644 --- a/src/main/snort.cc +++ b/src/main/snort.cc @@ -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(); diff --git a/src/main/snort.h b/src/main/snort.h index d5aad8b40..be543679d 100644 --- a/src/main/snort.h +++ b/src/main/snort.h @@ -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(); diff --git a/src/main/snort_config.cc b/src/main/snort_config.cc index 158627d60..4423ba06a 100644 --- a/src/main/snort_config.cc +++ b/src/main/snort_config.cc @@ -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; diff --git a/src/main/snort_config.h b/src/main/snort_config.h index cec685753..861f1de79 100644 --- a/src/main/snort_config.h +++ b/src/main/snort_config.h @@ -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; diff --git a/src/main/swapper.cc b/src/main/swapper.cc index ebed3b727..0e05f76da 100644 --- a/src/main/swapper.cc +++ b/src/main/swapper.cc @@ -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 ) diff --git a/src/managers/action_manager.cc b/src/managers/action_manager.cc index 4bd79a52a..82ca0c683 100644 --- a/src/managers/action_manager.cc +++ b/src/managers/action_manager.cc @@ -23,55 +23,66 @@ #include "action_manager.h" -#include +#include #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 AList; -static AList s_actors; +struct IpsActionsConfig +{ + vector clist; + IpsAction* reject = nullptr; +}; + +typedef vector 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 ∾ } + } + + 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(); } diff --git a/src/managers/action_manager.h b/src/managers/action_manager.h index c9af1bddc..774fe5003 100644 --- a/src/managers/action_manager.h +++ b/src/managers/action_manager.h @@ -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*); diff --git a/src/packet_io/active.cc b/src/packet_io/active.cc index 27e34874f..cadbcde16 100644 --- a/src/packet_io/active.cc +++ b/src/packet_io/active.cc @@ -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 ) {