diff --git a/cmake/modules/driver.cmake b/cmake/modules/driver.cmake index d9fd2b51..e9d34925 100644 --- a/cmake/modules/driver.cmake +++ b/cmake/modules/driver.cmake @@ -26,8 +26,8 @@ else() # In case you want to test against another driver version (or branch, or commit) just pass the variable - # ie., `cmake -DDRIVER_VERSION=dev ..` if(NOT DRIVER_VERSION) - set(DRIVER_VERSION "2a0c2c3d8cc069a9488680fd382233f28ed46791") - set(DRIVER_CHECKSUM "SHA256=179a1eeed098d29a4de93583be9b4a36cc9a8900b1c211dfa842b8c3a299c6a2") + set(DRIVER_VERSION "7cdd608db39287417a09c5c4743cd90efde7baec") + set(DRIVER_CHECKSUM "SHA256=ab9b621aad060b0dfddba0d7ee16f5f53ae72a7c9fe5dd84aadfed27046343e6") endif() # cd /path/to/build && cmake /path/to/source diff --git a/cmake/modules/falcosecurity-libs.cmake b/cmake/modules/falcosecurity-libs.cmake index 3c0b18fe..03efaa59 100644 --- a/cmake/modules/falcosecurity-libs.cmake +++ b/cmake/modules/falcosecurity-libs.cmake @@ -27,8 +27,8 @@ else() # In case you want to test against another falcosecurity/libs version (or branch, or commit) just pass the variable - # ie., `cmake -DFALCOSECURITY_LIBS_VERSION=dev ..` if(NOT FALCOSECURITY_LIBS_VERSION) - set(FALCOSECURITY_LIBS_VERSION "2a0c2c3d8cc069a9488680fd382233f28ed46791") - set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=179a1eeed098d29a4de93583be9b4a36cc9a8900b1c211dfa842b8c3a299c6a2") + set(FALCOSECURITY_LIBS_VERSION "7cdd608db39287417a09c5c4743cd90efde7baec") + set(FALCOSECURITY_LIBS_CHECKSUM "SHA256=ab9b621aad060b0dfddba0d7ee16f5f53ae72a7c9fe5dd84aadfed27046343e6") endif() # cd /path/to/build && cmake /path/to/source diff --git a/userspace/falco/CMakeLists.txt b/userspace/falco/CMakeLists.txt index f2d92403..9338dfa5 100644 --- a/userspace/falco/CMakeLists.txt +++ b/userspace/falco/CMakeLists.txt @@ -42,6 +42,7 @@ set( app_actions/start_webserver.cpp app_actions/validate_rules_files.cpp app_actions/create_requested_paths.cpp + app_actions/configure_interesting_sets.cpp configuration.cpp logger.cpp falco_outputs.cpp diff --git a/userspace/falco/app_actions/configure_interesting_sets.cpp b/userspace/falco/app_actions/configure_interesting_sets.cpp new file mode 100644 index 00000000..61654338 --- /dev/null +++ b/userspace/falco/app_actions/configure_interesting_sets.cpp @@ -0,0 +1,43 @@ +/* +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. +*/ + +#include "application.h" + +using namespace falco::app; + +void application::configure_interesting_sets() +{ + /// TODO: in the next future we need to change the interface of `enforce_simple_ppm_sc_set` + /// and `enforce_sinsp_state_tracepoints` APIs, they shouldn't require an inspector to be called! + std::unique_ptr inspector(new sinsp()); + + /* Please note: here we fill these 2 sets because we are interested in only some features, if we leave + * them empty `libsinsp` will fill them with all the available syscalls and all the available tracepoints! + */ + + /* Here the `libsinsp` state set is not enough, we need other syscalls used in the rules, + * so we use the `simple_set`, this `simple_set` contains all the syscalls of the `libsinsp` state + * plus syscalls for Falco default rules. + */ + m_state->ppm_sc_of_interest = inspector->enforce_simple_ppm_sc_set(); + + /* In this case we get the tracepoints for the `libsinsp` state and we remove + * the `sched_switch` tracepoint since it is highly noisy and not so useful + * for our state/events enrichment. + */ + m_state->tp_of_interest = inspector->enforce_sinsp_state_tracepoints(); + m_state->tp_of_interest.erase(SCHED_SWITCH); +} diff --git a/userspace/falco/app_actions/init_inspectors.cpp b/userspace/falco/app_actions/init_inspectors.cpp index 743122ae..14d21469 100644 --- a/userspace/falco/app_actions/init_inspectors.cpp +++ b/userspace/falco/app_actions/init_inspectors.cpp @@ -48,11 +48,7 @@ void application::init_syscall_inspector( if(!opts.all_events) { - m_state->ppm_sc_of_interest = inspector->enforce_simple_ppm_sc_set(); - m_state->tp_of_interest = inspector->enforce_sinsp_state_tracepoints(); - // We are not interested in sched_switch tracepoint, - // highly noisy and not useful for state/events enrichment. - m_state->tp_of_interest.erase(SCHED_SWITCH); + configure_interesting_sets(); } inspector->set_hostname_and_port_resolution_mode(false); diff --git a/userspace/falco/app_actions/load_rules_files.cpp b/userspace/falco/app_actions/load_rules_files.cpp index d7948fb4..57ea44fc 100644 --- a/userspace/falco/app_actions/load_rules_files.cpp +++ b/userspace/falco/app_actions/load_rules_files.cpp @@ -21,52 +21,58 @@ using namespace falco::app; void application::check_for_ignored_events() { - std::set evttypes; - std::unique_ptr inspector(new sinsp()); - sinsp_evttables* einfo = inspector->get_event_info_tables(); - const struct ppm_event_info* etable = einfo->m_event_info; - + /* Get the events from the rules. */ + std::set rule_events; std::string source = falco_common::syscall_source; - m_state->engine->evttypes_for_ruleset(source, evttypes); + m_state->engine->evttypes_for_ruleset(source, rule_events); - // Save event names so we don't warn for both the enter and exit event. - std::set warn_event_names; + /* Get the events we consider interesting from the application state `ppm_sc` codes. */ + std::unique_ptr inspector(new sinsp()); + auto interesting_events = inspector->get_event_set_from_ppm_sc_set(m_state->ppm_sc_of_interest); + std::unordered_set ignored_events; - for(auto evtnum : evttypes) + for(const auto& it : rule_events) { - if(evtnum == PPME_GENERIC_E || evtnum == PPME_GENERIC_X) + /* If we have the old version of the event we will have also the recent one + * so we can avoid analyzing the presence of old events. + */ + if(sinsp::is_old_version_event(it)) { continue; } - if(!simple_consumer_consider(etable[evtnum].flags, false)) + /* Here we are interested only in syscall events the internal events are not + * altered without the `-A` flag. + * + * TODO: We could consider also the tracepoint events here but right now we don't have + * the support from the libraries. + */ + if(!sinsp::is_syscall_event(it)) { - std::string name = etable[evtnum].name; - if(warn_event_names.find(name) == warn_event_names.end()) - { - warn_event_names.insert(name); - } + continue; + } + + /* If the event is not in this set it is not considered by Falco. */ + if(interesting_events.find(it) == interesting_events.end()) + { + ignored_events.insert(it); } } - // Print a single warning with the list of ignored events - if (!warn_event_names.empty()) + if(ignored_events.empty()) { - std::string skipped_events; - bool first = true; - for (const auto& evtname : warn_event_names) - { - if (first) - { - skipped_events += evtname; - first = false; - } else - { - skipped_events += "," + evtname; - } - } - fprintf(stderr,"Rules match ignored syscall: warning (ignored-evttype):\n loaded rules match the following events: %s;\n but these events are not returned unless running falco with -A\n", skipped_events.c_str()); + return; } + + /* Get the names of the ignored events and print them. */ + auto event_names = inspector->get_events_names(ignored_events); + std::cerr << std::endl << "Rules match ignored syscall: warning (ignored-evttype):" << std::endl; + std::cerr << "Loaded rules match the following events:" << std::endl; + for(const auto& it : event_names) + { + std::cerr << "\t- " << it.c_str() << std::endl; + } + std::cerr << "But these events are not returned unless running falco with -A" << std::endl << std::endl; } application::run_result application::load_rules_files() @@ -173,9 +179,10 @@ application::run_result application::load_rules_files() if(!m_options.all_events) { - // For syscalls, see if any event types used by the - // loaded rules are ones with the EF_DROP_SIMPLE_CONS - // label. + /* Here we have already initialized the application state with the interesting syscalls, + * so we have to check if any event types used by the loaded rules are not considered by + * Falco interesting set. + */ check_for_ignored_events(); } diff --git a/userspace/falco/app_actions/open_inspector.cpp b/userspace/falco/app_actions/open_inspector.cpp index a2d47ebb..4adb3ce6 100644 --- a/userspace/falco/app_actions/open_inspector.cpp +++ b/userspace/falco/app_actions/open_inspector.cpp @@ -46,29 +46,30 @@ application::run_result application::open_live_inspector( { try { - if (source != falco_common::syscall_source) + if (source != falco_common::syscall_source) /* Plugin engine */ { for (const auto& p: inspector->get_plugin_manager()->plugins()) { if (p->caps() & CAP_SOURCING && p->event_source() == source) { auto cfg = m_state->plugin_configs.at(p->name()); + falco_logger::log(LOG_INFO, "Falco uses the '" + cfg->m_name + "' plugin\n"); inspector->open_plugin(cfg->m_name, cfg->m_open_params); return run_result::ok(); } } return run_result::fatal("Can't open inspector for plugin event source: " + source); } - - if (m_options.userspace) + else if (m_options.userspace) /* udig engine. */ { // open_udig() is the underlying method used in the capture code to parse userspace events from the kernel. // // Falco uses a ptrace(2) based userspace implementation. // Regardless of the implementation, the underlying method remains the same. + falco_logger::log(LOG_INFO, "Starting capture with udig\n"); inspector->open_udig(); } - else if(!m_options.gvisor_config.empty()) + else if(!m_options.gvisor_config.empty()) /* gvisor engine. */ { falco_logger::log(LOG_INFO, "Enabled event collection from gVisor. Configuration path: " + m_options.gvisor_config); inspector->open_gvisor(m_options.gvisor_config, m_options.gvisor_root); @@ -88,19 +89,20 @@ application::run_result application::open_live_inspector( snprintf(full_path, PATH_MAX, "%s/%s", home, FALCO_PROBE_BPF_FILEPATH); bpf_probe_path = full_path; } - inspector->open_bpf(bpf_probe_path, DEFAULT_DRIVER_BUFFER_BYTES_DIM, m_state->ppm_sc_of_interest, m_state->tp_of_interest); falco_logger::log(LOG_INFO, "Starting capture with BPF probe. BPF probe path: " + std::string(bpf_probe_path)); + inspector->open_bpf(bpf_probe_path, DEFAULT_DRIVER_BUFFER_BYTES_DIM, m_state->ppm_sc_of_interest, m_state->tp_of_interest); } else /* Kernel module (default). */ { try { - inspector->open_kmod(DEFAULT_DRIVER_BUFFER_BYTES_DIM, m_state->ppm_sc_of_interest, m_state->tp_of_interest); falco_logger::log(LOG_INFO, "Starting capture with Kernel module."); + inspector->open_kmod(DEFAULT_DRIVER_BUFFER_BYTES_DIM, m_state->ppm_sc_of_interest, m_state->tp_of_interest); } catch(sinsp_exception &e) { // Try to insert the Falco kernel module + falco_logger::log(LOG_INFO, "Trying to inject the Kernel module and starting the capture again..."); if(system("modprobe " DRIVER_NAME " > /dev/null 2> /dev/null")) { falco_logger::log(LOG_ERR, "Unable to load the driver.\n"); diff --git a/userspace/falco/app_actions/print_ignored_events.cpp b/userspace/falco/app_actions/print_ignored_events.cpp index 807d2ba5..68ff3100 100644 --- a/userspace/falco/app_actions/print_ignored_events.cpp +++ b/userspace/falco/app_actions/print_ignored_events.cpp @@ -18,55 +18,50 @@ limitations under the License. using namespace falco::app; -void application::print_all_ignored_events() -{ - std::unique_ptr inspector(new sinsp()); - sinsp_evttables* einfo = inspector->get_event_info_tables(); - const struct ppm_event_info* etable = einfo->m_event_info; - const struct ppm_syscall_desc* stable = einfo->m_syscall_info_table; - - std::set ignored_event_names; - for(uint32_t j = 0; j < PPM_EVENT_MAX; j++) - { - if(!simple_consumer_consider(etable[j].flags)) - { - std::string name = etable[j].name; - // Ignore event names NA* - if(name.find("NA") != 0) - { - ignored_event_names.insert(name); - } - } - } - - auto simple_set = inspector->enforce_simple_ppm_sc_set(); - for(uint32_t j = 0; j < PPM_SC_MAX; j++) - { - if(simple_set.find(j) == simple_set.end()) - { - std::string name = stable[j].name; - // Ignore event names NA* - if(name.find("NA") != 0) - { - ignored_event_names.insert(name); - } - } - } - - printf("Ignored Event(s):"); - for(const auto& it : ignored_event_names) - { - printf(" %s", it.c_str()); - } - printf("\n"); -} - +/// TODO: probably in the next future would be more meaningful to print the ignored syscalls rather than +/// the ignored events, or maybe change the name of the events since right now they are almost the same of +/// the syscalls. application::run_result application::print_ignored_events() { - if(m_options.print_ignored_events) + /* If the option is true we print the events ignored with Falco `-A`, otherwise + * we return immediately. + */ + if(!m_options.print_ignored_events) { - print_all_ignored_events(); - return run_result::exit(); + return run_result::ok(); } - return run_result::ok(); + + /* Fill the application syscall and tracepoint sets. + * The execution will be interrupted after this call so + * we don't care if we populate these sets even if the `-A` flag + * is not set. + */ + configure_interesting_sets(); + + /* Search for all the ignored syscalls. */ + std::unique_ptr inspector(new sinsp()); + std::unordered_set all_ppm_sc = inspector->get_all_ppm_sc(); + std::unordered_set ignored_ppm_sc; + + for(const auto& it : all_ppm_sc) + { + /* If the syscall is not in this set we ignore it. */ + if(m_state->ppm_sc_of_interest.find(it) == m_state->ppm_sc_of_interest.end()) + { + ignored_ppm_sc.insert(it); + } + } + + /* Obtain the ignored events names from the ignored syscalls. */ + auto ignored_events = inspector->get_event_set_from_ppm_sc_set(ignored_ppm_sc); + auto event_names = inspector->get_events_names(ignored_events); + + std::cout << "Ignored Event(s):" << std::endl; + for(const auto& it : event_names) + { + std::cout << "- " << it.c_str() << std::endl; + } + std::cout << std::endl; + + return run_result::exit(); } diff --git a/userspace/falco/app_actions/process_events.cpp b/userspace/falco/app_actions/process_events.cpp index 3ddf0d20..09cfc856 100644 --- a/userspace/falco/app_actions/process_events.cpp +++ b/userspace/falco/app_actions/process_events.cpp @@ -189,7 +189,9 @@ application::run_result application::do_inspect( return run_result::fatal("Drop manager internal error"); } - if (!(simple_consumer_consider(ev->get_info_flags()) || m_options.all_events)) + /* If we have not set the `-A` flag and the event is unused or old, interrupt the flow */ + uint16_t evt_type = ev->get_type(); + if(!m_options.all_events && (sinsp::is_unused_event(evt_type) || sinsp::is_old_version_event(evt_type))) { continue; } diff --git a/userspace/falco/application.h b/userspace/falco/application.h index b6a0e508..aee0565d 100644 --- a/userspace/falco/application.h +++ b/userspace/falco/application.h @@ -249,6 +249,7 @@ private: run_result print_version(); run_result process_events(); run_result select_event_sources(); + void configure_interesting_sets(); #ifndef MINIMAL_BUILD run_result start_grpc_server(); run_result start_webserver(); @@ -269,7 +270,6 @@ private: bool create_handler(int sig, void (*func)(int), run_result &ret); void configure_output_format(); void check_for_ignored_events(); - void print_all_ignored_events(); 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); @@ -299,16 +299,6 @@ private: return !m_options.gvisor_config.empty(); } - bool simple_consumer_consider(int flags, bool old_version = true) const - { - int ignored_flagset = EF_SKIPPARSERESET | EF_UNUSED; - if (old_version) - { - ignored_flagset |= EF_OLD_VERSION; - } - return !(flags & ignored_flagset); - } - std::unique_ptr m_state; cmdline_options m_options; bool m_initialized; diff --git a/userspace/falco/event_drops.cpp b/userspace/falco/event_drops.cpp index ef4bf121..07d2a0b0 100644 --- a/userspace/falco/event_drops.cpp +++ b/userspace/falco/event_drops.cpp @@ -117,7 +117,7 @@ bool syscall_evt_drop_mgr::process_event(std::shared_ptr inspector, sinsp { m_num_actions++; - return perform_actions(evt->get_ts(), delta, inspector->is_bpf_enabled()); + return perform_actions(evt->get_ts(), delta, inspector->check_current_engine(BPF_ENGINE)); } else {