From: Bhargava Jandhyala (bjandhya) Date: Wed, 9 Jun 2021 06:30:14 +0000 (+0000) Subject: Merge pull request #2933 in SNORT/snort3 from ~DIPANDIT/snort3:multichannel_shared_pt... X-Git-Tag: 3.1.6.0~13 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a8cffabe41254ed71d2b5ceab4811fb41ed80470;p=thirdparty%2Fsnort3.git Merge pull request #2933 in SNORT/snort3 from ~DIPANDIT/snort3:multichannel_shared_ptr to master Squashed commit of the following: commit 98177702616043e80f1c7c20df6b4731696c763a Author: Dipto Pandit (dipandit) Date: Tue Jun 8 13:37:02 2021 -0400 dce_rpc: store shared pointer of session tracker commit e6a88c3afe70c9d690489cd5f004ce2782bab9b6 Author: Dipto Pandit (dipandit) Date: Tue Jun 8 07:47:55 2021 -0400 dce_rpc: handle reload prune for smb session cache --- diff --git a/src/service_inspectors/dce_rpc/dce_smb2.cc b/src/service_inspectors/dce_rpc/dce_smb2.cc index 1fe8b11b2..7e985db0d 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2.cc +++ b/src/service_inspectors/dce_rpc/dce_smb2.cc @@ -142,21 +142,21 @@ Smb2SessionKey Dce2Smb2SessionData::get_session_key(uint64_t session_id) return key; } -Dce2Smb2SessionTracker* Dce2Smb2SessionData::find_session(uint64_t session_id) +Dce2Smb2SessionTrackerPtr Dce2Smb2SessionData::find_session(uint64_t session_id) { std::lock_guard guard(session_data_mutex); auto it_session = connected_sessions.find(session_id); if (it_session != connected_sessions.end()) { - Dce2Smb2SessionTracker* session = it_session->second; + Dce2Smb2SessionTrackerPtr session = it_session->second; //we already have the session, but call find to update the LRU smb2_session_cache.find_session(session->get_key(), this); return session; } else { - Dce2Smb2SessionTracker* session = smb2_session_cache.find_session( + Dce2Smb2SessionTrackerPtr session = smb2_session_cache.find_session( get_session_key(session_id), this); if (session) connected_sessions.insert(std::make_pair(session_id,session)); @@ -165,18 +165,20 @@ Dce2Smb2SessionTracker* Dce2Smb2SessionData::find_session(uint64_t session_id) } // Caller must ensure that the session is not already present in flow -Dce2Smb2SessionTracker* Dce2Smb2SessionData::create_session(uint64_t session_id) +Dce2Smb2SessionTrackerPtr Dce2Smb2SessionData::create_session(uint64_t session_id) { Smb2SessionKey session_key = get_session_key(session_id); std::lock_guard guard(session_data_mutex); - Dce2Smb2SessionTracker* session = smb2_session_cache.find_else_create_session(session_key, this); + Dce2Smb2SessionTrackerPtr session = smb2_session_cache.find_else_create_session(session_key, this); connected_sessions.insert(std::make_pair(session_id, session)); return session; } -void Dce2Smb2SessionData::remove_session(uint64_t session_id) +void Dce2Smb2SessionData::remove_session(uint64_t session_id, bool sync) { + if (sync) session_data_mutex.lock(); connected_sessions.erase(session_id); + if (sync) session_data_mutex.unlock(); } void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr, @@ -235,7 +237,7 @@ void Dce2Smb2SessionData::process_command(const Smb2Hdr* smb_hdr, flow_key, Smb2Mid(smb_hdr), session_id, Smb2Tid(smb_hdr)); // Try to find the session. // The case when session is not available will be handled per command. - Dce2Smb2SessionTracker* session = find_session(session_id); + Dce2Smb2SessionTrackerPtr session = find_session(session_id); switch (command) { diff --git a/src/service_inspectors/dce_rpc/dce_smb2.h b/src/service_inspectors/dce_rpc/dce_smb2.h index 1d04cee84..222c4e2e4 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2.h +++ b/src/service_inspectors/dce_rpc/dce_smb2.h @@ -295,8 +295,9 @@ struct Smb2TreeConnectResponseHdr class Dce2Smb2FileTracker; class Dce2Smb2SessionTracker; +using Dce2Smb2SessionTrackerPtr = std::shared_ptr; using Dce2Smb2SessionTrackerMap = - std::unordered_map >; + std::unordered_map >; PADDING_GUARD_BEGIN struct Smb2SessionKey @@ -444,7 +445,7 @@ public: Dce2Smb2SessionData(const snort::Packet*, const dce2SmbProtoConf* proto); ~Dce2Smb2SessionData() override; void process() override; - void remove_session(uint64_t); + void remove_session(uint64_t, bool = false); void handle_retransmit(FilePosition, FileVerdict) override { } void reset_matching_tcp_file_tracker(Dce2Smb2FileTracker*); void set_reassembled_data(uint8_t*, uint16_t) override; @@ -458,8 +459,8 @@ public: private: void process_command(const Smb2Hdr*, const uint8_t*); Smb2SessionKey get_session_key(uint64_t); - Dce2Smb2SessionTracker* create_session(uint64_t); - Dce2Smb2SessionTracker* find_session(uint64_t); + Dce2Smb2SessionTrackerPtr create_session(uint64_t); + Dce2Smb2SessionTrackerPtr find_session(uint64_t); uint32_t flow_key; Dce2Smb2FileTracker* tcp_file_tracker; diff --git a/src/service_inspectors/dce_rpc/dce_smb2_session.cc b/src/service_inspectors/dce_rpc/dce_smb2_session.cc index d5f10faea..d823fe818 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2_session.cc +++ b/src/service_inspectors/dce_rpc/dce_smb2_session.cc @@ -176,6 +176,14 @@ void Dce2Smb2SessionTracker::decrease_size(const size_t size) smb2_session_cache.decrease_size(size); } +void Dce2Smb2SessionTracker::unlink() +{ + attached_flows_mutex.lock(); + for (auto it_flow : attached_flows) + it_flow.second->remove_session(session_id, reload_prune.load()); + attached_flows_mutex.unlock(); +} + // Session Tracker is created and destroyed only from session cache Dce2Smb2SessionTracker::~Dce2Smb2SessionTracker(void) { @@ -185,15 +193,20 @@ Dce2Smb2SessionTracker::~Dce2Smb2SessionTracker(void) "session tracker %" PRIu64 " terminating\n", session_id); } + std::vector all_trees; + connected_trees_mutex.lock(); auto it_tree = connected_trees.begin(); while (it_tree != connected_trees.end()) { - Dce2Smb2TreeTracker* tree = it_tree->second; + all_trees.push_back(it_tree->second); it_tree = connected_trees.erase(it_tree); + } + connected_trees_mutex.unlock(); + + for (Dce2Smb2TreeTracker* tree : all_trees) + { delete tree; } - for (auto it_flow : attached_flows) - it_flow.second->remove_session(session_id); } diff --git a/src/service_inspectors/dce_rpc/dce_smb2_session.h b/src/service_inspectors/dce_rpc/dce_smb2_session.h index b99ff52bc..a96153c46 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2_session.h +++ b/src/service_inspectors/dce_rpc/dce_smb2_session.h @@ -35,6 +35,7 @@ public: { session_id = key.sid; session_key = key; + reload_prune = false; debug_logf(dce_smb_trace, GET_CURRENT_PACKET, "session tracker %" PRIu64 " created\n", session_id); } @@ -64,10 +65,12 @@ public: Smb2SessionKey get_key() { return session_key; } void clean_file_context_from_flow(Dce2Smb2FileTracker*, uint64_t, uint64_t); + void unlink(); Dce2Smb2SessionData* get_flow(uint32_t); void process(const uint16_t, uint8_t, const Smb2Hdr*, const uint8_t*, const uint32_t); void increase_size(const size_t size); void decrease_size(const size_t size); + void set_reload_prune() { reload_prune = true; } private: Dce2Smb2TreeTracker* find_tree_for_message(const uint64_t, const uint32_t); @@ -75,6 +78,7 @@ private: Smb2SessionKey session_key; Dce2Smb2SessionDataMap attached_flows; Dce2Smb2TreeTrackerMap connected_trees; + std::atomic reload_prune; std::mutex connected_trees_mutex; std::mutex attached_flows_mutex; }; diff --git a/src/service_inspectors/dce_rpc/dce_smb2_session_cache.h b/src/service_inspectors/dce_rpc/dce_smb2_session_cache.h index 6a19c4689..982a095e9 100644 --- a/src/service_inspectors/dce_rpc/dce_smb2_session_cache.h +++ b/src/service_inspectors/dce_rpc/dce_smb2_session_cache.h @@ -40,21 +40,23 @@ public: Dce2Smb2SharedCache(const size_t initial_size) : LruCacheShared(initial_size) { } - Value* find_session(Key key, Dce2Smb2SessionData* ssd) + using Data = std::shared_ptr; + + Data find_session(Key key, Dce2Smb2SessionData* ssd) { flow_mutex.lock(); - Value* session = this->find(key).get(); + Data session = this->find(key); if (session) session->attach_flow(ssd->get_flow_key(), ssd); flow_mutex.unlock(); return session; } - Value* find_else_create_session(Key& key, Dce2Smb2SessionData* ssd) + Data find_else_create_session(Key& key, Dce2Smb2SessionData* ssd) { - std::shared_ptr new_session = std::shared_ptr(new Value(key)); + Data new_session = Data(new Value(key)); flow_mutex.lock(); - Value* session = this->find_else_insert(key, new_session, nullptr).get(); + Data session = this->find_else_insert(key, new_session, nullptr); session->attach_flow(ssd->get_flow_key(), ssd); flow_mutex.unlock(); return session; @@ -76,9 +78,38 @@ public: current_size -= size; } + // Since decrease_size() does not account for associated objects in smb2_session_cache, + // we will over-prune when we reach the new_size here, as more space will be freed up + // when actual objects are destroyed. We might need to do gradual pruning like how + // host cache does. For now over pruning is ok. + void reload_prune(size_t new_size) + { + Purgatory data; + std::lock_guard cache_lock(cache_mutex); + max_size = new_size; + while (current_size > max_size && !list.empty()) + { + LruListIter list_iter = --list.end(); + data.emplace_back(list_iter->second); // increase reference count + // This instructs the session_tracker to take a lock before detaching + // from ssd, when it is getting destroyed. + list_iter->second->set_reload_prune(); + decrease_size(list_iter->second.get()); + map.erase(list_iter->first); + list.erase(list_iter); + ++stats.reload_prunes; + } + } + private: - using LruCacheShared::current_size; - using LruCacheShared::cache_mutex; + using LruBase = LruCacheShared; + using LruBase::cache_mutex; + using LruBase::current_size; + using LruBase::list; + using LruBase::map; + using LruBase::max_size; + using LruBase::stats; + using LruListIter = typename LruBase::LruListIter; std::mutex flow_mutex; void increase_size(Value* value_ptr=nullptr) override { @@ -91,6 +122,8 @@ private: { assert(current_size >= sizeof(*value_ptr) ); current_size -= sizeof(*value_ptr); + //This is going down, remove references from flow here + value_ptr->unlink(); } } }; diff --git a/src/service_inspectors/dce_rpc/dce_smb_inspector.cc b/src/service_inspectors/dce_rpc/dce_smb_inspector.cc index 65924ab6b..174b81a86 100644 --- a/src/service_inspectors/dce_rpc/dce_smb_inspector.cc +++ b/src/service_inspectors/dce_rpc/dce_smb_inspector.cc @@ -129,7 +129,7 @@ static Inspector* dce2_smb_ctor(Module* m) mod->get_data(config); size_t max_smb_mem = DCE2_ScSmbMemcap(&config); smb_module_is_up = true; - smb2_session_cache.set_max_size(max_smb_mem); + smb2_session_cache.reload_prune(max_smb_mem); return new Dce2Smb(config); }