mirror of
https://github.com/falcosecurity/falco.git
synced 2026-02-21 06:02:30 +00:00
update: falco works with the latest libs commit
Signed-off-by: Andrea Terzolo <andrea.terzolo@polito.it>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
43
userspace/falco/app_actions/configure_interesting_sets.cpp
Normal file
43
userspace/falco/app_actions/configure_interesting_sets.cpp
Normal 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);
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user