diff --git a/userspace/falco/app/actions/configure_interesting_sets.h b/userspace/falco/app/actions/configure_interesting_sets.h deleted file mode 100644 index 11c2f0f3..00000000 --- a/userspace/falco/app/actions/configure_interesting_sets.h +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright (C) 2023 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#include -#include - -std::string concat_syscalls_names(std::unordered_set const syscalls_names); -// TODO interim helper methods below shall be integrated into sinsp APIs -std::unordered_set get_syscalls_ppm_codes(const std::unordered_set syscalls_names); -std::unordered_set get_difference_syscalls_names(std::unordered_set syscalls_names_reference, std::unordered_set syscalls_names_comparison); diff --git a/userspace/falco/app/actions/helpers_interesting_sets.cpp b/userspace/falco/app/actions/helpers_interesting_sets.cpp index 1f125767..f11cc3c3 100644 --- a/userspace/falco/app/actions/helpers_interesting_sets.cpp +++ b/userspace/falco/app/actions/helpers_interesting_sets.cpp @@ -17,7 +17,6 @@ limitations under the License. #include "helpers.h" #include "actions.h" -#include "configure_interesting_sets.h" #include "falco_utils.h" #include #include diff --git a/userspace/falco/application.cpp b/userspace/falco/application.cpp deleted file mode 100644 index 835bff48..00000000 --- a/userspace/falco/application.cpp +++ /dev/null @@ -1,249 +0,0 @@ -/* -Copyright (C) 2022 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// The falco "app" holds application-level configuration and contains -// the implementation of any subcommand-like behaviors like --list, -i -// (print_ignored_events), etc. - -// It also contains the code to initialize components like the -// inspector, falco engine, etc. - -#include "application.h" -#include "falco_common.h" - -using namespace std::placeholders; - -static inline bool should_take_action_to_signal(std::atomic& v) -{ - // we expected the signal to be received, and we try to set action-taken flag - int value = APP_SIGNAL_SET; - while (!v.compare_exchange_weak( - value, - APP_SIGNAL_ACTION_TAKEN, - std::memory_order_seq_cst, - std::memory_order_seq_cst)) - { - // application already took action, there's no need to do it twice - if (value == APP_SIGNAL_ACTION_TAKEN) - { - return false; - } - - // signal did was not really received, so we "fake" receiving it - if (value == APP_SIGNAL_NOT_SET) - { - v.store(APP_SIGNAL_SET, std::memory_order_seq_cst); - } - - // reset "expected" CAS variable and keep looping until we succeed - value = APP_SIGNAL_SET; - } - return true; -} - -namespace falco { -namespace app { - -std::atomic g_terminate(APP_SIGNAL_NOT_SET); -std::atomic g_restart(APP_SIGNAL_NOT_SET); -std::atomic g_reopen_outputs(APP_SIGNAL_NOT_SET); - -application::run_result::run_result() - : success(true), errstr(""), proceed(true) -{ -} - -application::run_result::~run_result() -{ -} - -application::state::state() - : loaded_sources(), - enabled_sources(), - source_infos(), - plugin_configs(), - ppm_sc_of_interest(), - tp_of_interest(), - syscall_buffer_bytes_size(DEFAULT_DRIVER_BUFFER_BYTES_DIM) -{ - config = std::make_shared(); - engine = std::make_shared(); - offline_inspector = std::make_shared(); - outputs = nullptr; -} - -application::state::~state() -{ -} - -application::application() - : m_initialized(false) -{ -} - -application::~application() -{ -} - -void application::terminate(bool verbose) -{ - if (should_take_action_to_signal(falco::app::g_terminate)) - { - if (verbose) - { - falco_logger::log(LOG_INFO, "SIGINT received, exiting...\n"); - } - } -} - -void application::reopen_outputs(bool verbose) -{ - if (should_take_action_to_signal(falco::app::g_reopen_outputs)) - { - if (verbose) - { - falco_logger::log(LOG_INFO, "SIGUSR1 received, reopening outputs...\n"); - } - if(m_state != nullptr && m_state->outputs != nullptr) - { - m_state->outputs->reopen_outputs(); - } - falco::app::g_reopen_outputs.store(APP_SIGNAL_NOT_SET); - } -} - -void application::restart(bool verbose) -{ - if (should_take_action_to_signal(falco::app::g_restart)) - { - if (verbose) - { - falco_logger::log(LOG_INFO, "SIGHUP received, restarting...\n"); - } - } -} - -bool application::init(int argc, char **argv, std::string &errstr) -{ - if(m_initialized) - { - throw falco_exception("Application already initialized"); - } - - m_state.reset(new state()); - - if(!m_options.parse(argc, argv, errstr)) - { - return false; - } - - for(char **arg = argv; *arg; arg++) - { - if(m_state->cmdline.size() > 0) - { - m_state->cmdline += " "; - } - m_state->cmdline += *arg; - } - - m_initialized = true; - return true; -} - -bool application::run(std::string &errstr, bool &restart) -{ - run_result res; - - // The order here is the order in which the methods will be - // called. Before changing the order, ensure that all - // dependencies are honored (e.g. don't process events before - // loading plugins, opening inspector, etc.). - std::list> run_steps = { - std::bind(&application::load_config, this), - std::bind(&application::print_help, this), - std::bind(&application::print_version, this), - std::bind(&application::print_page_size, this), - std::bind(&application::print_ignored_events, this), - std::bind(&application::print_syscall_events, this), - std::bind(&application::print_generated_gvisor_config, this), - std::bind(&application::require_config_file, this), - std::bind(&application::print_plugin_info, this), - std::bind(&application::list_plugins, this), - std::bind(&application::load_plugins, this), - std::bind(&application::init_inspectors, this), - std::bind(&application::init_falco_engine, this), - std::bind(&application::list_fields, this), - std::bind(&application::select_event_sources, this), - std::bind(&application::validate_rules_files, this), - std::bind(&application::load_rules_files, this), - std::bind(&application::print_support, this), - std::bind(&application::create_signal_handlers, this), - std::bind(&application::attach_inotify_signals, this), - std::bind(&application::create_requested_paths, this), - std::bind(&application::daemonize, this), - std::bind(&application::init_outputs, this), - std::bind(&application::init_clients, this), - std::bind(&application::configure_interesting_sets, this), - std::bind(&application::configure_syscall_buffer_size, this), -#ifndef MINIMAL_BUILD - std::bind(&application::start_grpc_server, this), - std::bind(&application::start_webserver, this), -#endif - std::bind(&application::process_events, this) - }; - - std::list> teardown_steps = { - std::bind(&application::unregister_signal_handlers, this, _1), -#ifndef MINIMAL_BUILD - std::bind(&application::stop_grpc_server, this, _1), - std::bind(&application::stop_webserver, this, _1) -#endif - }; - - for (auto &func : run_steps) - { - res = func(); - - if(!res.proceed) - { - break; - } - } - - for (auto &func : teardown_steps) - { - std::string errstr; - - if(!func(errstr)) - { - // Note only printing warning here--we want all functions - // to occur even if some return errors. - fprintf(stderr, "Could not tear down in run(): %s\n", errstr.c_str()); - } - } - - if(!res.success) - { - errstr = res.errstr; - } - - restart = should_restart(); - - return res.success; -} - -}; // namespace app -}; // namespace falco diff --git a/userspace/falco/application.h b/userspace/falco/application.h deleted file mode 100644 index fbeac822..00000000 --- a/userspace/falco/application.h +++ /dev/null @@ -1,414 +0,0 @@ -/* -Copyright (C) 2022 The Falco Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#pragma once - -#include "semaphore.h" -#include "configuration.h" -#include "stats_writer.h" -#ifndef MINIMAL_BUILD -#include "grpc_server.h" -#include "webserver.h" -#include "indexed_vector.h" -#endif - -#include "app_cmdline_options.h" - -#include -#include -#include - -#define APP_SIGNAL_NOT_SET 0 // The signal flag is not set -#define APP_SIGNAL_SET 1 // The signal flag has been set -#define APP_SIGNAL_ACTION_TAKEN 2 // The signal flag has been set and the application took action - -namespace falco { -namespace app { - -// these are used to control the lifecycle of the application -// through signal handlers or internal calls -extern std::atomic g_terminate; -extern std::atomic g_restart; -extern std::atomic g_reopen_outputs; - -class application { -public: - application(); - virtual ~application(); - application(application&&) = default; - application& operator = (application&&) = default; - application(const application&) = delete; - application& operator = (const application&) = delete; - - bool init(int argc, char **argv, std::string &errstr); - - // Returns whether the application completed with errors or - // not. errstr will contain details when run() returns false. - // - // If restart (generally set by signal handlers) is - // true, the application should be restarted instead of - // exiting. - bool run(std::string &errstr, bool &restart); - -private: - // Holds the state used and shared by the below methods that - // actually implement the application. Declared as a - // standalone class to allow for a bit of separation between - // application state and instance variables, and to also defer - // initializing this state until application::init. - struct state - { - // Holds the info mapped for each loaded event source - struct source_info - { - // The index of the given event source in the state's falco_engine, - // as returned by falco_engine::add_source - std::size_t engine_idx; - // The filtercheck list containing all fields compatible - // with the given event source - filter_check_list filterchecks; - // The inspector assigned to this event source. If in capture mode, - // all event source will share the same inspector. If the event - // source is a plugin one, the assigned inspector must have that - // plugin registered in its plugin manager - std::shared_ptr inspector; - }; - - state(); - virtual ~state(); - - std::shared_ptr config; - std::shared_ptr outputs; - std::shared_ptr engine; - - // The set of loaded event sources (by default, the syscall event - // source plus all event sources coming from the loaded plugins) - std::unordered_set loaded_sources; - - // The set of enabled event sources (can be altered by using - // the --enable-source and --disable-source options) - std::unordered_set enabled_sources; - - // Used to load all plugins to get their info. In capture mode, - // this is also used to open the capture file and read its events - std::shared_ptr offline_inspector; - - // List of all the information mapped to each event source - // indexed by event source name - indexed_vector source_infos; - - // List of all plugin configurations indexed by plugin name as returned - // by their sinsp_plugin::name method - indexed_vector plugin_configs; - - std::string cmdline; - - // Set of events we want the driver to capture - std::unordered_set ppm_event_info_of_interest; - - // Set of syscalls we want the driver to capture - std::unordered_set ppm_sc_of_interest; - - // Set of tracepoints we want the driver to capture - std::unordered_set tp_of_interest; - - // Dimension of the syscall buffer in bytes. - uint64_t syscall_buffer_bytes_size; - -#ifndef MINIMAL_BUILD - falco::grpc::server grpc_server; - std::thread grpc_server_thread; - - falco_webserver webserver; -#endif - }; - - // Used in the below methods to indicate how to proceed. - struct run_result { - // Successful result - inline static run_result ok() - { - run_result r; - r.success = true; - r.errstr = ""; - r.proceed = true; - return r; - } - - // Successful result that causes the program to stop - inline static run_result exit() - { - run_result r = ok(); - r.proceed = false; - return r; - } - - // Failure result that causes the program to stop with an error - inline static run_result fatal(const std::string& err) - { - run_result r; - r.success = false; - r.errstr = err; - r.proceed = false; - return r; - } - - // Merges two run results into one - inline static run_result merge(const run_result& a, const run_result& b) - { - auto res = ok(); - res.proceed = a.proceed && b.proceed; - res.success = a.success && b.success; - res.errstr = a.errstr; - if (!b.errstr.empty()) - { - res.errstr += res.errstr.empty() ? "" : "\n"; - res.errstr += b.errstr; - } - return res; - } - - run_result(); - virtual ~run_result(); - run_result(run_result&&) = default; - run_result& operator = (run_result&&) = default; - run_result(const run_result&) = default; - run_result& operator = (const run_result&) = default; - - - // If true, the method completed successfully. - bool success; - // If success==false, details on the error. - std::string errstr; - // If true, subsequent methods should be performed. If - // false, subsequent methods should *not* be performed - // and falco should tear down/exit/restart. - bool proceed; - }; - - // used to synchronize different event source running in parallel - class source_sync_context - { - public: - source_sync_context(falco::semaphore& s) - : m_finished(false), m_joined(false), m_semaphore(s) { } - source_sync_context(source_sync_context&&) = default; - source_sync_context& operator = (source_sync_context&&) = default; - source_sync_context(const source_sync_context&) = delete; - source_sync_context& operator = (const source_sync_context&) = delete; - - inline void finish() - { - bool v = false; - while (!m_finished.compare_exchange_weak( - v, true, - std::memory_order_seq_cst, - std::memory_order_seq_cst)) - { - if (v) - { - throw falco_exception("source_sync_context has been finished twice"); - } - } - m_semaphore.release(); - } - - inline void join() - { - bool v = false; - while (!m_joined.compare_exchange_weak( - v, true, - std::memory_order_seq_cst, - std::memory_order_seq_cst)) - { - if (v) - { - throw falco_exception("source_sync_context has been joined twice"); - } - } - } - - inline bool joined() - { - return m_joined.load(std::memory_order_seq_cst); - } - - inline bool finished() - { - return m_finished.load(std::memory_order_seq_cst); - } - - private: - // set to true when the event processing loop finishes - std::atomic m_finished; - // set to true when the result has been collected after finishing - std::atomic m_joined; - // used to notify the waiting thread when finished gets set to true - falco::semaphore& m_semaphore; - }; - - // Convenience method. Read a sequence of filenames and fill - // in a vector of rules contents. - // Also fill in the provided rules_contents_t with a mapping from - // filename (reference) to content (reference). - // falco_exception if any file could not be read. - template - void read_files(InputIterator begin, InputIterator end, - std::vector& rules_contents, - falco::load_result::rules_contents_t& rc) - { - // Read the contents in a first pass - for(auto it = begin; it != end; it++) - { - std::string &filename = *it; - std::ifstream is; - is.open(filename); - if (!is.is_open()) - { - throw falco_exception("Could not open file " + filename + " for reading"); - } - - std::string rules_content((istreambuf_iterator(is)), - istreambuf_iterator()); - rules_contents.emplace_back(std::move(rules_content)); - } - - // Populate the map in a second pass to avoid - // references becoming invalid. - auto it = begin; - auto rit = rules_contents.begin(); - for(; it != end && rit != rules_contents.end(); it++, rit++) - { - rc.emplace(*it, *rit); - } - - // Both it and rit must be at the end, otherwise - // there's a bug in the above - if(it != end || rit != rules_contents.end()) - { - throw falco_exception("Unexpected mismatch in rules content name/rules content sets?"); - } - } - - // These methods comprise the code the application "runs". The - // order in which the methods run is in application.cpp. - run_result create_signal_handlers(); - run_result attach_inotify_signals(); - run_result daemonize(); - run_result init_falco_engine(); - run_result init_inspectors(); - run_result init_clients(); - run_result init_outputs(); - run_result list_fields(); - run_result list_plugins(); - run_result load_config(); - run_result require_config_file(); - run_result load_plugins(); - run_result load_rules_files(); - run_result create_requested_paths(); - run_result print_generated_gvisor_config(); - run_result print_help(); - run_result print_ignored_events(); - run_result print_plugin_info(); - run_result print_support(); - run_result print_syscall_events(); - run_result print_version(); - run_result print_page_size(); - run_result process_events(); - run_result select_event_sources(); - run_result configure_interesting_sets(); - application::run_result configure_syscall_buffer_size(); -#ifndef MINIMAL_BUILD - run_result start_grpc_server(); - run_result start_webserver(); -#endif - run_result validate_rules_files(); - - // These methods comprise application teardown. The order in - // which the methods run is in application.cpp. - bool close_inspector(std::string &errstr); - bool unregister_signal_handlers(std::string &errstr); -#ifndef MINIMAL_BUILD - bool stop_grpc_server(std::string &errstr); - bool stop_webserver(std::string &errstr); -#endif - - // Methods called by the above methods - int create_dir(const std::string &path); - bool create_handler(int sig, void (*func)(int), run_result &ret); - void configure_output_format(); - void check_for_unsupported_events(std::unique_ptr& inspector, const std::unordered_set& rules_evttypes_names); - bool check_rules_plugin_requirements(std::string& err); - std::unordered_set extract_rules_event_names(std::unique_ptr& inspector); // should be called before syscalls and events activations - void activate_interesting_syscalls(std::unique_ptr& inspector, const std::unordered_set& rules_evttypes_names); - void activate_interesting_events(std::unique_ptr& inspector, const std::unordered_set& rules_evttypes_names); // should be called after calling activate_interesting_syscalls - void activate_interesting_kernel_tracepoints(std::unique_ptr& inspector); // independent of syscalls and events activations in terms of order - void format_plugin_info(std::shared_ptr p, std::ostream& os) const; - run_result open_offline_inspector(); - run_result open_live_inspector(std::shared_ptr inspector, const std::string& source); - void add_source_to_engine(const std::string& src); - void print_enabled_event_sources(); - void init_syscall_inspector(std::shared_ptr inspector, const falco::app::cmdline_options& opts); - run_result do_inspect( - std::shared_ptr inspector, - const std::string& source, // an empty source represents capture mode - std::shared_ptr statsw, - syscall_evt_drop_mgr &sdropmgr, - bool check_drops_and_timeouts, - uint64_t duration_to_tot_ns, - uint64_t &num_evts); - void process_inspector_events( - std::shared_ptr inspector, - std::shared_ptr statsw, - std::string source, // an empty source represents capture mode - application::source_sync_context* sync, - run_result* res) noexcept; - - /* Returns true if we are in capture mode. */ - inline bool is_capture_mode() const - { - return !m_options.trace_filename.empty(); - } - - inline bool is_gvisor_enabled() const - { - return !m_options.gvisor_config.empty(); - } - - // used in signal handlers to control the flow of the application - void terminate(bool verbose=true); - void restart(bool verbose=true); - void reopen_outputs(bool verbose=true); - inline bool should_terminate() - { - return g_terminate.load(std::memory_order_seq_cst) != APP_SIGNAL_NOT_SET; - } - inline bool should_restart() - { - return g_restart.load(std::memory_order_seq_cst) != APP_SIGNAL_NOT_SET; - } - inline bool should_reopen_outputs() - { - return g_reopen_outputs.load(std::memory_order_seq_cst) != APP_SIGNAL_NOT_SET; - } - - std::unique_ptr m_state; - cmdline_options m_options; - bool m_initialized; -}; - -}; // namespace app -}; // namespace falco