diff --git a/userspace/falco/app/actions/helpers_interesting_sets.cpp b/userspace/falco/app/actions/helpers_interesting_sets.cpp index 1f9ce1b4..49f5f4ee 100644 --- a/userspace/falco/app/actions/helpers_interesting_sets.cpp +++ b/userspace/falco/app/actions/helpers_interesting_sets.cpp @@ -19,7 +19,10 @@ limitations under the License. using namespace falco::app; using namespace falco::app::actions; -void extract_base_syscalls_names(const std::unordered_set& base_syscalls_names, std::unordered_set& positive_names, std::unordered_set& negative_names) +static void extract_base_syscalls_names( + const std::unordered_set& base_syscalls_names, + std::unordered_set& user_positive_names, + std::unordered_set& user_negative_names) { for (const std::string &ev : base_syscalls_names) { @@ -27,58 +30,41 @@ void extract_base_syscalls_names(const std::unordered_set& base_sys { if (ev.at(0) == '!') { - negative_names.insert(ev.substr(1, ev.size())); + user_negative_names.insert(ev.substr(1, ev.size())); } else { - positive_names.insert(ev); + user_positive_names.insert(ev); } } } } -static libsinsp::events::set extract_rules_event_set(falco::app::state& s) -{ - /* Get all (positive) PPME events from all rules as idx codes. - * Events names from negative filter expression statements are NOT included. - * PPME events in libsinsp are needed to map each event type into it's enter - * and exit event if applicable (e.g. for syscall events). */ - std::set tmp; - libsinsp::events::set events; - auto source = falco_common::syscall_source; - s.engine->evttypes_for_ruleset(source, tmp); - for (const auto &ev : tmp) - { - events.insert((ppm_event_code) ev); - } - return events; -} - -static void check_for_rules_unsupported_events(falco::app::state& s, const libsinsp::events::set& rules_event_set) +static void check_for_rules_unsupported_events(falco::app::state& s, const libsinsp::events::set& rules_sc_set) { /* Unsupported events are those events that are used in the rules * but that are not part of the selected event set. For now, this * is expected to happen only for high volume I/O syscalls for * performance reasons. */ - auto unsupported_event_set = rules_event_set.diff(s.selected_event_set); - if (unsupported_event_set.empty()) + auto unsupported_sc_set = rules_sc_set.diff(s.selected_sc_set); + if (unsupported_sc_set.empty()) { return; } /* Get the names of the events (syscall and non syscall events) that were not activated and print them. */ - auto names = libsinsp::events::event_set_to_names(unsupported_event_set); + auto names = libsinsp::events::sc_set_to_names(unsupported_sc_set); std::cerr << "Loaded rules match event types that are not activated or unsupported with current configuration: warning (unsupported-evttype): " + concat_set_in_order(names) << std::endl; std::cerr << "If syscalls in rules include high volume I/O syscalls (-> activate via `-A` flag), else syscalls might be associated with syscalls undefined on your architecture (https://marcin.juszkiewicz.com.pl/download/tables/syscalls.html)" << std::endl; } -static void select_event_set(falco::app::state& s, libsinsp::events::set& rules_event_set) +static void select_event_set(falco::app::state& s, const libsinsp::events::set& rules_sc_set) { /* PPM syscall codes (sc) can be viewed as condensed libsinsp lookup table * to map a system call name to it's actual system syscall id (as defined * by the Linux kernel). Hence here we don't need syscall enter and exit distinction. */ - auto rules_names = libsinsp::events::event_set_to_names(rules_event_set); - if (!rules_event_set.empty()) + auto rules_names = libsinsp::events::sc_set_to_names(rules_sc_set); + if (!rules_sc_set.empty()) { falco_logger::log(LOG_DEBUG, "(" + std::to_string(rules_names.size()) + ") events in rules: " + concat_set_in_order(rules_names) + "\n"); @@ -94,68 +80,55 @@ static void select_event_set(falco::app::state& s, libsinsp::events::setm_base_syscalls; - libsinsp::events::set valid_positive_syscalls; - if (!user_base_syscalls_names.empty()) + /* USER OVERRIDE INPUT OPTION "base_syscalls". */ + std::unordered_set user_positive_names = {}; + std::unordered_set user_negative_names = {}; + extract_base_syscalls_names(s.config->m_base_syscalls, user_positive_names, user_negative_names); + auto user_positive_sc_set = libsinsp::events::names_to_sc_set(user_positive_names); + auto user_negative_sc_set = libsinsp::events::names_to_sc_set(user_negative_names); + + if (!user_positive_sc_set.empty()) { - /* USER OVERRIDE INPUT OPTION "base_syscalls". */ - std::unordered_set positive_names = {}; - std::unordered_set negative_names = {}; - extract_base_syscalls_names(user_base_syscalls_names, positive_names, negative_names); + // user overrides base event set + base_sc_set = user_positive_sc_set; - valid_positive_syscalls = libsinsp::events::names_to_sc_set(positive_names); - auto valid_negative_syscalls = libsinsp::events::names_to_sc_set(negative_names); + // we re-transform from events set to names to make + // sure that bad user inputs are ignored + auto user_positive_sc_set_names = libsinsp::events::sc_set_to_names(user_positive_sc_set); + falco_logger::log(LOG_DEBUG, "+(" + std::to_string(user_positive_sc_set_names.size()) + + ") syscalls added (base_syscalls override): " + + concat_set_in_order(user_positive_sc_set_names) + "\n"); + } - if (!valid_positive_syscalls.empty()) - { - /* Convert valid syscalls codes to event codes. */ - auto valid_positive_events = libsinsp::events::sc_set_to_event_set(valid_positive_syscalls); + // selected events are the union of the rules events set and the + // base events set (either the default or the user-defined one) + s.selected_sc_set = rules_sc_set.merge(base_sc_set); - /* For now remove the sinsp_state_sc_set again. A possible future libs refactor can remove this need. - * That way we consistently use sinsp_state_event_set() which adds critical non syscalls events. - * This step prepares the sinsp state enforcement override w/ "base_syscalls" user input. - */ - auto sc_state_event_set = libsinsp::events::sc_set_to_event_set(libsinsp::events::sinsp_state_sc_set()); - s.selected_event_set = s.selected_event_set.diff(sc_state_event_set); - s.selected_event_set = rules_event_set.merge(s.selected_event_set); + if (!user_negative_sc_set.empty()) + { + /* Remove negative base_syscalls events. */ + s.selected_sc_set = s.selected_sc_set.diff(user_negative_sc_set); - /* Add valid base_syscalls events. */ - s.selected_event_set = s.selected_event_set.merge(valid_positive_events); - - auto valid_positive_syscalls_names = libsinsp::events::sc_set_to_names(valid_positive_syscalls); - falco_logger::log(LOG_DEBUG, "+(" + std::to_string(valid_positive_syscalls_names.size()) - + ") syscalls added (base_syscalls override): " - + concat_set_in_order(valid_positive_syscalls_names) + "\n"); - } - - if (!valid_negative_syscalls.empty()) - { - /* Convert valid syscalls codes to event codes. */ - auto valid_negative_events = libsinsp::events::sc_set_to_event_set(valid_negative_syscalls); - - /* Remove negative base_syscalls events. */ - s.selected_event_set = s.selected_event_set.diff(valid_negative_events); - rules_event_set = rules_event_set.diff(valid_negative_events); - - auto valid_negative_syscalls_names = libsinsp::events::sc_set_to_names(valid_negative_syscalls); - falco_logger::log(LOG_DEBUG, "-(" + std::to_string(valid_negative_syscalls_names.size()) - + ") syscalls removed (base_syscalls override): " - + concat_set_in_order(valid_negative_syscalls_names) + "\n"); - } + // we re-transform from events set to names to make + // sure that bad user inputs are ignored + auto user_negative_sc_set_names = libsinsp::events::sc_set_to_names(user_negative_sc_set); + falco_logger::log(LOG_DEBUG, "-(" + std::to_string(user_negative_sc_set_names.size()) + + ") syscalls removed (base_syscalls override): " + + concat_set_in_order(user_negative_sc_set_names) + "\n"); } /* Derive the diff between the additional syscalls added via libsinsp state - enforcement and the syscalls from each Falco rule. */ - auto non_rules_event_set = s.selected_event_set.diff(rules_event_set); - if (!non_rules_event_set.empty() && valid_positive_syscalls.empty()) + enforcement and the syscalls from each Falco rule. We avoid printing + this in case the user specified a custom set of base syscalls */ + auto non_rules_sc_set = s.selected_sc_set.diff(rules_sc_set); + if (!non_rules_sc_set.empty() && user_positive_sc_set.empty()) { - auto non_rules_event_set_names = libsinsp::events::event_set_to_names(non_rules_event_set); - falco_logger::log(LOG_DEBUG, "+(" + std::to_string(non_rules_event_set_names.size()) + auto non_rules_sc_set_names = libsinsp::events::sc_set_to_names(non_rules_sc_set); + falco_logger::log(LOG_DEBUG, "+(" + std::to_string(non_rules_sc_set_names.size()) + ") events (Falco's state engine set of events): " - + concat_set_in_order(non_rules_event_set_names) + "\n"); + + concat_set_in_order(non_rules_sc_set_names) + "\n"); } /* -A flag behavior: @@ -165,35 +138,23 @@ static void select_event_set(falco::app::state& s, libsinsp::events::set activate via `-A` flag): " - + concat_set_in_order(erased_event_set_names) + "\n"); + + concat_set_in_order(erased_sc_set_names) + "\n"); } } - if (!s.selected_event_set.empty()) - { - auto selected_event_set_names = libsinsp::events::event_set_to_names(s.selected_event_set); - falco_logger::log(LOG_DEBUG, "(" + std::to_string(selected_event_set_names.size()) - + ") events selected in total (final set): " - + concat_set_in_order(selected_event_set_names) + "\n"); - } -} - -static void select_syscall_set(falco::app::state& s, const libsinsp::events::set& rules_event_set) -{ - s.selected_sc_set = libsinsp::events::event_set_to_sc_set(s.selected_event_set); if (!s.selected_sc_set.empty()) { auto selected_sc_set_names = libsinsp::events::sc_set_to_names(s.selected_sc_set); falco_logger::log(LOG_DEBUG, "(" + std::to_string(selected_sc_set_names.size()) - + ") syscalls selected in total (final set): " + + ") events selected in total (final set): " + concat_set_in_order(selected_sc_set_names) + "\n"); } } @@ -210,7 +171,11 @@ static void select_kernel_tracepoint_set(falco::app::state& s) falco::app::run_result falco::app::actions::configure_interesting_sets(falco::app::state& s) { - s.selected_event_set.clear(); + if (s.engine == nullptr || s.config == nullptr) + { + return run_result::fatal("Broken 'configure_interesting_sets' preconditions: engine and config must be non-null"); + } + s.selected_sc_set.clear(); s.selected_tp_set.clear(); @@ -222,10 +187,9 @@ falco::app::run_result falco::app::actions::configure_interesting_sets(falco::ap * of syscall codes. Those last two sets will be passed down to the * inspector to instruct the kernel drivers on which kernel event should * be collected at runtime. */ - auto rules_event_set = extract_rules_event_set(s); - select_event_set(s, rules_event_set); - check_for_rules_unsupported_events(s, rules_event_set); - select_syscall_set(s, rules_event_set); + auto rules_sc_set = s.engine->sc_codes_for_ruleset(falco_common::syscall_source); + select_event_set(s, rules_sc_set); + check_for_rules_unsupported_events(s, rules_sc_set); select_kernel_tracepoint_set(s); return run_result::ok(); } diff --git a/userspace/falco/app/state.h b/userspace/falco/app/state.h index 7f79028a..8ba9b19f 100644 --- a/userspace/falco/app/state.h +++ b/userspace/falco/app/state.h @@ -63,7 +63,6 @@ struct state enabled_sources(), source_infos(), plugin_configs(), - selected_event_set(), selected_sc_set(), selected_tp_set(), syscall_buffer_bytes_size(DEFAULT_DRIVER_BUFFER_BYTES_DIM) @@ -106,9 +105,6 @@ struct state // by their sinsp_plugin::name method indexed_vector plugin_configs; - // Set of events we want the driver to capture - libsinsp::events::set selected_event_set; - // Set of syscalls we want the driver to capture libsinsp::events::set selected_sc_set;