update: falco works with the latest libs commit

Signed-off-by: Andrea Terzolo <andrea.terzolo@polito.it>
This commit is contained in:
Andrea Terzolo
2022-09-18 16:50:17 +00:00
committed by poiana
parent e068df514c
commit 7e37c72431
11 changed files with 146 additions and 110 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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<sinsp> 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);
}

View File

@@ -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);

View File

@@ -21,52 +21,58 @@ using namespace falco::app;
void application::check_for_ignored_events()
{
std::set<uint16_t> evttypes;
std::unique_ptr<sinsp> 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<uint16_t> 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<std::string> warn_event_names;
/* Get the events we consider interesting from the application state `ppm_sc` codes. */
std::unique_ptr<sinsp> inspector(new sinsp());
auto interesting_events = inspector->get_event_set_from_ppm_sc_set(m_state->ppm_sc_of_interest);
std::unordered_set<uint32_t> 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();
}

View File

@@ -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");

View File

@@ -18,55 +18,50 @@ limitations under the License.
using namespace falco::app;
void application::print_all_ignored_events()
{
std::unique_ptr<sinsp> 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<string> 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<sinsp> inspector(new sinsp());
std::unordered_set<uint32_t> all_ppm_sc = inspector->get_all_ppm_sc();
std::unordered_set<uint32_t> 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();
}

View File

@@ -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;
}

View File

@@ -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<sinsp_plugin> p, std::ostream& os) const;
run_result open_offline_inspector();
run_result open_live_inspector(std::shared_ptr<sinsp> 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<state> m_state;
cmdline_options m_options;
bool m_initialized;

View File

@@ -117,7 +117,7 @@ bool syscall_evt_drop_mgr::process_event(std::shared_ptr<sinsp> 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
{