From: Russ Combs (rucombs) Date: Thu, 26 Mar 2020 22:53:55 +0000 (+0000) Subject: Merge pull request #2083 in SNORT/snort3 from ~SBAIGAL/snort3:so_proxy to master X-Git-Tag: 3.0.1-1~8 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0eef6709bcbe3b5049b6a8e60073ff6827eefd59;p=thirdparty%2Fsnort3.git Merge pull request #2083 in SNORT/snort3 from ~SBAIGAL/snort3:so_proxy to master Squashed commit of the following: commit f19ea58fa5e667524c554164ab956346e1abe04a Author: Steven Baigal (sbaigal) Date: Tue Mar 10 18:11:14 2020 -0400 so_rule: fix reload of shared object rules that use flow data add tracking SO rule flow data with so_proxy inspector --- diff --git a/src/flow/CMakeLists.txt b/src/flow/CMakeLists.txt index fb5a7d036..34ff1be24 100644 --- a/src/flow/CMakeLists.txt +++ b/src/flow/CMakeLists.txt @@ -1,6 +1,7 @@ set (FLOW_INCLUDES expect_cache.h flow.h + flow_data.h flow_key.h flow_stash.h ha.h @@ -16,6 +17,7 @@ add_library (flow OBJECT flow_config.h flow_control.cc flow_control.h + flow_data.cc flow_key.cc flow_stash.cc flow_stash.h diff --git a/src/flow/flow.cc b/src/flow/flow.cc index d9a2e2fd5..ffac79d04 100644 --- a/src/flow/flow.cc +++ b/src/flow/flow.cc @@ -28,7 +28,6 @@ #include "flow/session.h" #include "framework/data_bus.h" #include "ips_options/ips_flowbits.h" -#include "memory/memory_cap.h" #include "protocols/packet.h" #include "sfip/sf_ip.h" #include "utils/bitop.h" @@ -37,43 +36,6 @@ using namespace snort; -unsigned FlowData::flow_data_id = 0; - -FlowData::FlowData(unsigned u, Inspector* ph) -{ - assert(u > 0); - id = u; - handler = ph; - prev = next = nullptr; - if ( handler ) - handler->add_ref(); -} - -FlowData::~FlowData() -{ - if ( handler ) - handler->rem_ref(); - - assert(mem_in_use == 0); -} - -void FlowData::update_allocations(size_t n) -{ - memory::MemoryCap::free_space(n); - memory::MemoryCap::update_allocations(n); - mem_in_use += n; -} - -void FlowData::update_deallocations(size_t n) -{ - assert(mem_in_use >= n); - memory::MemoryCap::update_deallocations(n); - mem_in_use -= n; -} - -size_t FlowData::size_of() -{ return 1024; } // FIXIT-H remove this default impl - Flow::Flow() { memset(this, 0, sizeof(*this)); diff --git a/src/flow/flow.h b/src/flow/flow.h index 5f02ae58d..8e2bd8b0f 100644 --- a/src/flow/flow.h +++ b/src/flow/flow.h @@ -30,6 +30,7 @@ #include #include "detection/ips_context_chain.h" +#include "flow/flow_data.h" #include "flow/flow_stash.h" #include "framework/data_bus.h" #include "framework/decode_data.h" @@ -108,42 +109,6 @@ struct Packet; typedef void (* StreamAppDataFree)(void*); -class SO_PUBLIC FlowData -{ -public: - FlowData(unsigned u, Inspector* = nullptr); - virtual ~FlowData(); - - unsigned get_id() - { return id; } - - static unsigned create_flow_data_id() - { return ++flow_data_id; } - - void update_allocations(size_t); - void update_deallocations(size_t); - Inspector* get_handler() { return handler; } - - // return fixed size (could be an approx avg) - // this must be fixed for life of flow data instance - // track significant supplemental allocations with the above updaters - virtual size_t size_of() = 0; - - virtual void handle_expected(Packet*) { } - virtual void handle_retransmit(Packet*) { } - virtual void handle_eof(Packet*) { } - -public: // FIXIT-L privatize - FlowData* next; - FlowData* prev; - -private: - static unsigned flow_data_id; - Inspector* handler; - size_t mem_in_use = 0; - unsigned id; -}; - struct FlowStats { uint64_t client_pkts; diff --git a/src/flow/flow_data.cc b/src/flow/flow_data.cc new file mode 100644 index 000000000..af6f9b017 --- /dev/null +++ b/src/flow/flow_data.cc @@ -0,0 +1,71 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2020-2020 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- +// flow_data.cc author Russ Combs + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "flow_data.h" + +#include + +#include "framework/inspector.h" +#include "main/snort_config.h" +#include "managers/so_manager.h" +#include "memory/memory_cap.h" + +using namespace snort; + +unsigned FlowData::flow_data_id = 0; + +FlowData::FlowData(unsigned u, Inspector* ph) +{ + assert(u > 0); + id = u; + handler = ph; + prev = next = nullptr; + if ( handler ) + handler->add_ref(); +} + +FlowData::~FlowData() +{ + if ( handler ) + handler->rem_ref(); + + assert(mem_in_use == 0); +} + +void FlowData::update_allocations(size_t n) +{ + memory::MemoryCap::free_space(n); + memory::MemoryCap::update_allocations(n); + mem_in_use += n; +} + +void FlowData::update_deallocations(size_t n) +{ + assert(mem_in_use >= n); + memory::MemoryCap::update_deallocations(n); + mem_in_use -= n; +} + +RuleFlowData::RuleFlowData(unsigned u) : FlowData(u, + SnortConfig::get_conf()->so_rules->proxy) { } + diff --git a/src/flow/flow_data.h b/src/flow/flow_data.h new file mode 100644 index 000000000..6a19e2373 --- /dev/null +++ b/src/flow/flow_data.h @@ -0,0 +1,77 @@ +//-------------------------------------------------------------------------- +// Copyright (C) 2020-2020 Cisco and/or its affiliates. All rights reserved. +// +// This program is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License Version 2 as published +// by the Free Software Foundation. You may not use, modify or distribute +// this program under any other version of the GNU General Public License. +// +// This program is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +//-------------------------------------------------------------------------- +// flow_data.h author Russ Combs + +#ifndef FLOW_DATA_H +#define FLOW_DATA_H + +#include "main/snort_types.h" + +namespace snort +{ +class Inspector; +struct Packet; + +class SO_PUBLIC FlowData +{ +public: + FlowData(unsigned u, Inspector* = nullptr); + virtual ~FlowData(); + + unsigned get_id() + { return id; } + + static unsigned create_flow_data_id() + { return ++flow_data_id; } + + void update_allocations(size_t); + void update_deallocations(size_t); + Inspector* get_handler() { return handler; } + + // return fixed size (could be an approx avg) + // this must be fixed for life of flow data instance + // track significant supplemental allocations with the above updaters + virtual size_t size_of() = 0; + + virtual void handle_expected(Packet*) { } + virtual void handle_retransmit(Packet*) { } + virtual void handle_eof(Packet*) { } + +public: // FIXIT-L privatize + FlowData* next; + FlowData* prev; + +private: + static unsigned flow_data_id; + Inspector* handler; + size_t mem_in_use = 0; + unsigned id; +}; + +// The flow data created from SO rules must use RuleFlowData +// to support reload +class SO_PUBLIC RuleFlowData : public FlowData +{ +protected: + RuleFlowData(unsigned u); +public: + virtual ~RuleFlowData() { } +}; + +} +#endif diff --git a/src/flow/test/CMakeLists.txt b/src/flow/test/CMakeLists.txt index df99e24f7..fe0a2b09f 100644 --- a/src/flow/test/CMakeLists.txt +++ b/src/flow/test/CMakeLists.txt @@ -23,5 +23,7 @@ add_cpputest( flow_cache_test add_cpputest( session_test ) add_cpputest( flow_test - SOURCES ../flow.cc + SOURCES + ../flow.cc + ../flow_data.cc ) diff --git a/src/flow/test/flow_test.cc b/src/flow/test/flow_test.cc index cac9f8a8b..759987293 100644 --- a/src/flow/test/flow_test.cc +++ b/src/flow/test/flow_test.cc @@ -23,17 +23,18 @@ #include "config.h" #endif -#include "protocols/ip.h" -#include "protocols/layer.h" -#include "protocols/packet.h" +#include "detection/detection_engine.h" #include "flow/flow.h" #include "flow/flow_stash.h" #include "flow/ha.h" -#include "main/snort_debug.h" #include "framework/inspector.h" #include "framework/data_bus.h" +#include "main/snort_config.h" +#include "main/snort_debug.h" #include "memory/memory_cap.h" -#include "detection/detection_engine.h" +#include "protocols/ip.h" +#include "protocols/layer.h" +#include "protocols/packet.h" #include #include @@ -82,6 +83,8 @@ const Layer* layer::get_mpls_layer(const Packet* const) { return nullptr; } void DataBus::publish(const char*, Packet*, Flow*) {} +SnortConfig* SnortConfig::get_conf() { return nullptr; } + TEST_GROUP(nondefault_timeout) { void setup() override diff --git a/src/framework/base_api.h b/src/framework/base_api.h index 06d955868..00d181a51 100644 --- a/src/framework/base_api.h +++ b/src/framework/base_api.h @@ -29,7 +29,7 @@ // this is the current version of the base api // must be prefixed to subtype version -#define BASE_API_VERSION 1 +#define BASE_API_VERSION 2 // set options to API_OPTIONS to ensure compatibility #ifndef API_OPTIONS diff --git a/src/host_tracker/test/host_cache_module_test.cc b/src/host_tracker/test/host_cache_module_test.cc index e048064c0..0db2a0b78 100644 --- a/src/host_tracker/test/host_cache_module_test.cc +++ b/src/host_tracker/test/host_cache_module_test.cc @@ -82,6 +82,14 @@ HostCacheAllocIp::HostCacheAllocIp() lru = &host_cache; } +template +void HostCacheAlloc::deallocate(T* p, std::size_t n) noexcept +{ + size_t sz = n*sizeof(T); + std::allocator::deallocate(p, n); + lru->update( -(int) sz); +} + TEST_GROUP(host_cache_module) { void setup() override diff --git a/src/managers/coreinit.lua b/src/managers/coreinit.lua index 04b114fa2..7f607870d 100644 --- a/src/managers/coreinit.lua +++ b/src/managers/coreinit.lua @@ -38,6 +38,7 @@ output = { } packets = { } process = { } search_engine = { } +so_proxy = { } -- exceptions: diff --git a/src/managers/plugin_manager.cc b/src/managers/plugin_manager.cc index 63fc5a3f1..172d65d00 100644 --- a/src/managers/plugin_manager.cc +++ b/src/managers/plugin_manager.cc @@ -398,6 +398,8 @@ void PluginManager::load_plugins(const BaseApi** lp) void PluginManager::load_plugins(const std::string& paths) { + SoManager::load_so_proxy(); + // dynamic plugins if ( !paths.empty() ) ::load_plugins(paths); diff --git a/src/managers/so_manager.cc b/src/managers/so_manager.cc index 8c8c8b046..f2eeec4a9 100644 --- a/src/managers/so_manager.cc +++ b/src/managers/so_manager.cc @@ -33,6 +33,9 @@ #include #include "log/messages.h" +#include "framework/decode_data.h" +#include "framework/inspector.h" +#include "framework/module.h" #include "main/snort_config.h" #include "parser/parse_so_rule.h" @@ -337,3 +340,92 @@ void SoManager::rule_to_text(const char* delim) cout << "static const unsigned rule_" << var << "_len = 0;" << endl; } +//------------------------------------------------------------------------- +// so_proxy inspector +//------------------------------------------------------------------------- +static const char* sp_name = "so_proxy"; +static const char* sp_help = "a proxy inspector to track flow data from SO rules (internal use only)"; +class SoProxy : public Inspector +{ +public: + void eval(Packet*) override { } + bool configure(SnortConfig* sc) override + { + for( auto i : sc->so_rules->handles ) + handles.emplace_back(i); + sc->so_rules->proxy = this; + return true; + } + ~SoProxy() override { handles.clear(); } + +private: + std::list handles; +}; + +static const Parameter sp_params[] = +{ + { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } +}; + +class SoProxyModule : public Module +{ +public: + SoProxyModule() : Module(sp_name, sp_help, sp_params) { } + Usage get_usage() const override + { return GLOBAL; } +}; + +static Module* mod_ctor() +{ return new SoProxyModule; } + +static void mod_dtor(Module* m) +{ delete m; } + +static Inspector* sp_ctor(Module*) +{ + return new SoProxy; +} + +static void sp_dtor(Inspector* p) +{ + delete p; +} + +static const InspectApi so_proxy_api +{ + { + PT_INSPECTOR, + sizeof(InspectApi), + INSAPI_VERSION, + 0, + API_RESERVED, + API_OPTIONS, + sp_name, + sp_help, + mod_ctor, + mod_dtor + }, + IT_PASSIVE, + PROTO_BIT__NONE, + nullptr, // buffers + nullptr, // service + nullptr, // pinit + nullptr, // pterm + nullptr, // tinit, + nullptr, // tterm, + sp_ctor, + sp_dtor, + nullptr, // ssn + nullptr // reset +}; + +const BaseApi* so_proxy_plugins[] = +{ + &so_proxy_api.base, + nullptr +}; + +void SoManager::load_so_proxy() +{ + PluginManager::load_plugins(so_proxy_plugins); +} diff --git a/src/managers/so_manager.h b/src/managers/so_manager.h index bbcc89e19..03ea4d8b9 100644 --- a/src/managers/so_manager.h +++ b/src/managers/so_manager.h @@ -29,6 +29,7 @@ namespace snort { struct SnortConfig; +class Inspector; } //------------------------------------------------------------------------- @@ -36,6 +37,7 @@ struct SoRules { std::list api; std::list handles; + snort::Inspector* proxy = nullptr; ~SoRules(); }; @@ -56,6 +58,7 @@ public: static void rule_to_hex(const char* file); static void rule_to_text(const char* file); static void dump_rule_stubs(const char*, snort::SnortConfig*); + static void load_so_proxy(); }; #endif diff --git a/src/network_inspectors/appid/client_plugins/test/client_plugin_mock.h b/src/network_inspectors/appid/client_plugins/test/client_plugin_mock.h index 17010d100..e01a97e4a 100644 --- a/src/network_inspectors/appid/client_plugins/test/client_plugin_mock.h +++ b/src/network_inspectors/appid/client_plugins/test/client_plugin_mock.h @@ -101,6 +101,7 @@ AppIdConfig::~AppIdConfig() = default; // Stubs for AppIdPegCounts void AppIdPegCounts::inc_payload_count(AppId) { } +void AppIdPegCounts::inc_client_count(AppId) { } THREAD_LOCAL AppIdStats appid_stats;