From: RAGHURAAM CONJEEVARAM UDAYANAN -X (rconjeev - XORIANT CORPORATION at Cisco) Date: Mon, 9 Oct 2023 14:33:54 +0000 (+0000) Subject: Pull request #4019: control: blocking control connections X-Git-Tag: 3.1.72.0~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=77b26d896c3f54313998e80a26d629460d2af546;p=thirdparty%2Fsnort3.git Pull request #4019: control: blocking control connections Merge in SNORT/snort3 from ~RCONJEEV/snort3:control_conn_cmd_block_fix to master Squashed commit of the following: commit b1ad1e27d0f38286ac99594af11eb7d1c0cb94f8 Author: RAGHURAAM CONJEEVARAM UDAYANAN -X (rconjeev - XORIANT CORPORATION at Cisco) Date: Mon Sep 25 04:25:11 2023 -0400 control: allow one command at a time --- diff --git a/src/control/control.cc b/src/control/control.cc index 0204e82ac..da861dd0e 100644 --- a/src/control/control.cc +++ b/src/control/control.cc @@ -35,6 +35,7 @@ using namespace snort; std::vector ControlConn::log_exclusion_list; +unsigned ControlConn::pending_cmds_count = 0; ControlConn* ControlConn::query_from_lua(const lua_State* L) { @@ -66,6 +67,9 @@ ControlConn::~ControlConn() void ControlConn::shutdown() { + if (blocked) + blocked = false; + if (is_closed()) return; if (!local) @@ -168,6 +172,8 @@ int ControlConn::execute_commands() while (!is_closed() && !blocked && !pending_commands.empty()) { const std::string& command = pending_commands.front(); + if (pending_cmds_count && !ModuleManager::is_parallel_cmd(command)) + break; std::string rsp; shell->execute(command.c_str(), rsp); if (!rsp.empty()) diff --git a/src/control/control.h b/src/control/control.h index 8c4c67c49..71fea8bff 100644 --- a/src/control/control.h +++ b/src/control/control.h @@ -49,7 +49,6 @@ public: void unblock(); void remove(); bool show_prompt(); - bool is_blocked() const { return blocked; } bool is_closed() const { return (fd == -1); } bool is_removed() const { return removed; } @@ -70,6 +69,8 @@ public: SO_PUBLIC static ControlConn* query_from_lua(const lua_State*); static void log_command(const std::string& module, bool log); + static unsigned increment_pending_cmds_count() { return ++pending_cmds_count; } + static unsigned decrement_pending_cmds_count() { return --pending_cmds_count; } private: void touch(); @@ -81,11 +82,12 @@ private: class Shell *shell; int fd; bool local = false; - bool blocked = false; + bool blocked = false; //block any new commands from executing before current command in control connection is complete bool removed = false; time_t touched; static std::vector log_exclusion_list; + static unsigned pending_cmds_count; //counter to serialize commands across control connections }; #define LogRespond(cn, ...) do { if (cn) cn->respond(__VA_ARGS__); else LogMessage(__VA_ARGS__); } while(0) diff --git a/src/control/control_mgmt.cc b/src/control/control_mgmt.cc index 5c3aed10e..54f5ba09a 100644 --- a/src/control/control_mgmt.cc +++ b/src/control/control_mgmt.cc @@ -337,6 +337,35 @@ static void delete_control(int fd) delete_control(iter); } +static int execute_control_commands(ControlConn *ctrlcon) +{ + int executed = 0; + if (!ctrlcon) + return executed; + + executed = ctrlcon->execute_commands(); + if (executed > 0) + { + if (ctrlcon->is_local()) + proc_stats.local_commands += executed; + else + proc_stats.remote_commands += executed; + } + return executed; +} + +static void process_pending_control_commands() +{ + for (auto it : controls) + { + if (it.second->has_pending_command()) + { + ControlConn* ctrlcon = it.second; + execute_control_commands(ctrlcon); + } + } +} + static bool process_control_commands(int fd) { const auto iter = controls.find(fd); @@ -353,14 +382,7 @@ static bool process_control_commands(int fd) return false; } - int executed = ctrlcon->execute_commands(); - if (executed > 0) - { - if (ctrlcon->is_local()) - proc_stats.local_commands += executed; - else - proc_stats.remote_commands += executed; - } + int executed = execute_control_commands(ctrlcon); if (ctrlcon->is_closed()) delete_control(iter); @@ -490,6 +512,8 @@ bool ControlMgmt::service_users() static FdEvents event[MAX_CONTROL_FDS]; unsigned nevent; + process_pending_control_commands(); + if (!poll_control_fds(event, nevent)) return false; diff --git a/src/framework/module.h b/src/framework/module.h index 8eb3b75b1..e1c3001f3 100644 --- a/src/framework/module.h +++ b/src/framework/module.h @@ -66,6 +66,8 @@ struct Command LuaCFunction func; const Parameter* params; const char* help; + // the flag determines if the command is allowed to run in parallel with other control commands + bool can_run_in_parallel = false; std::string get_arg_list() const; }; diff --git a/src/main/ac_shell_cmd.cc b/src/main/ac_shell_cmd.cc index a4003a2ae..195f59a26 100644 --- a/src/main/ac_shell_cmd.cc +++ b/src/main/ac_shell_cmd.cc @@ -33,6 +33,7 @@ ACShellCmd::ACShellCmd(ControlConn* conn, AnalyzerCommand* ac) : AnalyzerCommand if (ctrlcon) ctrlcon->block(); + ControlConn::increment_pending_cmds_count(); } bool ACShellCmd::execute(Analyzer& analyzer, void** state) @@ -44,6 +45,7 @@ bool ACShellCmd::execute(Analyzer& analyzer, void** state) ACShellCmd::~ACShellCmd() { delete ac; + ControlConn::decrement_pending_cmds_count(); if (ctrlcon) { diff --git a/src/main/snort_module.cc b/src/main/snort_module.cc index 7b154673d..b73a68b69 100644 --- a/src/main/snort_module.cc +++ b/src/main/snort_module.cc @@ -147,14 +147,14 @@ static const Command snort_cmds[] = // FIXIT-M rewrite trough to permit updates on the fly //{ "process", main_process, nullptr, "process given pcap" }, - { "pause", main_pause, nullptr, "suspend packet processing" }, + { "pause", main_pause, nullptr, "suspend packet processing", true }, { "resume", main_resume, s_pktnum, "continue packet processing. " - "If number of packets is specified, will resume for n packets and pause" }, + "If number of packets is specified, will resume for n packets and pause", true }, - { "detach", main_detach, nullptr, "detach from control shell (without shutting down)" }, - { "quit", main_quit, nullptr, "shutdown and dump-stats" }, - { "help", main_help, nullptr, "this output" }, + { "detach", main_detach, nullptr, "detach from control shell (without shutting down)", true }, + { "quit", main_quit, nullptr, "shutdown and dump-stats", true }, + { "help", main_help, nullptr, "this output", true }, { nullptr, nullptr, nullptr, nullptr } }; diff --git a/src/managers/module_manager.cc b/src/managers/module_manager.cc index 2ef30a6cc..80cf9fe14 100644 --- a/src/managers/module_manager.cc +++ b/src/managers/module_manager.cc @@ -83,6 +83,7 @@ static string s_aliased_name; static string s_aliased_type; static string s_ips_includer; static string s_file_id_includer; +static std::unordered_set s_parallel_cmds; // for callbacks from Lua static SnortConfig* s_config = nullptr; @@ -157,11 +158,19 @@ void ModHook::init() // would be out of date, out of sync, etc. QED reg = new luaL_Reg[++n]; unsigned k = 0; - + std::string cmd_name; + const char* dot = "."; while ( k < n ) { reg[k].name = c[k].name; reg[k].func = c[k].func; + if (c[k].can_run_in_parallel) + { + cmd_name = mod->get_name(); + cmd_name = cmd_name + dot + c[k].name; + s_parallel_cmds.insert(cmd_name); + } + k++; } } @@ -1942,6 +1951,30 @@ void ModuleManager::show_modules_json() json.close_array(); } +bool ModuleManager::is_parallel_cmd(std::string control_cmd) +{ + control_cmd = remove_whitespace(control_cmd); + + std::string mod_cmd; + + size_t dotPos = control_cmd.find('.'); + size_t openParenthesisPos = control_cmd.find("("); + + if (dotPos == std::string::npos) + mod_cmd = "snort."; + + if (openParenthesisPos != std::string::npos) + mod_cmd = mod_cmd + control_cmd.substr(0,openParenthesisPos); + + return 1 == s_parallel_cmds.count(mod_cmd); +} + +std::string ModuleManager::remove_whitespace(std::string& control_cmd) +{ + control_cmd.erase(std::remove_if(control_cmd.begin(), control_cmd.end(), ::isspace), control_cmd.end()); + return control_cmd; +} + #ifdef UNIT_TEST #include diff --git a/src/managers/module_manager.h b/src/managers/module_manager.h index c09d10848..850ed38ba 100644 --- a/src/managers/module_manager.h +++ b/src/managers/module_manager.h @@ -94,6 +94,8 @@ public: static void reset_stats(clear_counter_type_t); static void clear_global_active_counters(); + static bool is_parallel_cmd(std::string control_cmd); + static std::string remove_whitespace(std::string& control_cmd); static std::set gids;