mirror of
https://github.com/falcosecurity/falco.git
synced 2026-03-24 13:42:09 +00:00
Compare commits
26 Commits
buffer_dim
...
feat/modul
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f1d676f949 | ||
|
|
73f70cd0ef | ||
|
|
b1edc405c2 | ||
|
|
efe39b4360 | ||
|
|
a04ac1def3 | ||
|
|
f710edcde2 | ||
|
|
7a3d5c62a0 | ||
|
|
435a3b01db | ||
|
|
acd3e7f23a | ||
|
|
deaae756c0 | ||
|
|
5a6c7af0c5 | ||
|
|
05565f3524 | ||
|
|
980fb2f3a9 | ||
|
|
ba5e59964d | ||
|
|
60721d52cb | ||
|
|
8d9f88d45a | ||
|
|
4c04821d48 | ||
|
|
fc2c1ac6cb | ||
|
|
295c7afc32 | ||
|
|
f10b170174 | ||
|
|
9f9d0e751b | ||
|
|
322a2cdd25 | ||
|
|
5c5c2e3309 | ||
|
|
71832bc3ad | ||
|
|
93a3d14c41 | ||
|
|
c7e7a868ed |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,10 +3,12 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
|
|
||||||
test/falco_tests.yaml
|
test/falco_tests.yaml
|
||||||
|
test/falco_traces.yaml
|
||||||
test/traces-negative
|
test/traces-negative
|
||||||
test/traces-positive
|
test/traces-positive
|
||||||
test/traces-info
|
test/traces-info
|
||||||
test/job-results
|
test/job-results
|
||||||
|
test/build
|
||||||
test/.phoronix-test-suite
|
test/.phoronix-test-suite
|
||||||
test/results*.json.*
|
test/results*.json.*
|
||||||
test/build
|
test/build
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ cmake_minimum_required(VERSION 3.3.2)
|
|||||||
project(falco)
|
project(falco)
|
||||||
|
|
||||||
if(NOT SYSDIG_DIR)
|
if(NOT SYSDIG_DIR)
|
||||||
get_filename_component(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig" REALPATH)
|
get_filename_component(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig" REALPATH)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Custom CMake modules
|
# Custom CMake modules
|
||||||
@@ -53,7 +53,7 @@ if(BUILD_WARNINGS_AS_ERRORS)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_COMMON_FLAGS}")
|
set(CMAKE_C_FLAGS "${CMAKE_COMMON_FLAGS}")
|
||||||
set(CMAKE_CXX_FLAGS "--std=c++0x ${CMAKE_COMMON_FLAGS}")
|
set(CMAKE_CXX_FLAGS "--std=c++11 ${CMAKE_COMMON_FLAGS}")
|
||||||
|
|
||||||
set(CMAKE_C_FLAGS_DEBUG "${DRAIOS_DEBUG_FLAGS}")
|
set(CMAKE_C_FLAGS_DEBUG "${DRAIOS_DEBUG_FLAGS}")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${DRAIOS_DEBUG_FLAGS}")
|
set(CMAKE_CXX_FLAGS_DEBUG "${DRAIOS_DEBUG_FLAGS}")
|
||||||
|
|||||||
20
falco.yaml
20
falco.yaml
@@ -80,7 +80,6 @@ buffered_outputs: false
|
|||||||
# The rate at which log/alert messages are emitted is governed by a
|
# The rate at which log/alert messages are emitted is governed by a
|
||||||
# token bucket. The rate corresponds to one message every 30 seconds
|
# token bucket. The rate corresponds to one message every 30 seconds
|
||||||
# with a burst of 10 messages.
|
# with a burst of 10 messages.
|
||||||
|
|
||||||
syscall_event_drops:
|
syscall_event_drops:
|
||||||
actions:
|
actions:
|
||||||
- log
|
- log
|
||||||
@@ -88,6 +87,21 @@ syscall_event_drops:
|
|||||||
rate: .03333
|
rate: .03333
|
||||||
max_burst: 10
|
max_burst: 10
|
||||||
|
|
||||||
|
# Options to configure the kernel module check.
|
||||||
|
# Falco uses a kernel module to obtain the info to match against the rules.
|
||||||
|
# In order to correctly behave it needs to ensure that the kernel module is always present and well behaving.
|
||||||
|
# The following options configure:
|
||||||
|
# the frequency it should check for the kernel module
|
||||||
|
# the maximum number of consecutive failures after which it should stop
|
||||||
|
# the exponential backoff mechanism it have to use to check for the module and eventally to try to re-insert it automatically.
|
||||||
|
module_check:
|
||||||
|
frequency: 10
|
||||||
|
max_consecutive_failures: 3
|
||||||
|
backoff:
|
||||||
|
max_attempts: 5
|
||||||
|
init_delay: 100
|
||||||
|
max_delay: 3000
|
||||||
|
|
||||||
# A throttling mechanism implemented as a token bucket limits the
|
# A throttling mechanism implemented as a token bucket limits the
|
||||||
# rate of falco notifications. This throttling is controlled by the following configuration
|
# rate of falco notifications. This throttling is controlled by the following configuration
|
||||||
# options:
|
# options:
|
||||||
@@ -99,14 +113,12 @@ syscall_event_drops:
|
|||||||
# an initial quiet period, and then up to 1 notification per second
|
# an initial quiet period, and then up to 1 notification per second
|
||||||
# afterward. It would gain the full burst back after 1000 seconds of
|
# afterward. It would gain the full burst back after 1000 seconds of
|
||||||
# no activity.
|
# no activity.
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
rate: 1
|
rate: 1
|
||||||
max_burst: 1000
|
max_burst: 1000
|
||||||
|
|
||||||
# Where security notifications should go.
|
# Where security notifications should go.
|
||||||
# Multiple outputs can be enabled.
|
# Multiple outputs can be enabled.
|
||||||
|
|
||||||
syslog_output:
|
syslog_output:
|
||||||
enabled: true
|
enabled: true
|
||||||
|
|
||||||
@@ -117,7 +129,6 @@ syslog_output:
|
|||||||
#
|
#
|
||||||
# Also, the file will be closed and reopened if falco is signaled with
|
# Also, the file will be closed and reopened if falco is signaled with
|
||||||
# SIGUSR1.
|
# SIGUSR1.
|
||||||
|
|
||||||
file_output:
|
file_output:
|
||||||
enabled: false
|
enabled: false
|
||||||
keep_alive: false
|
keep_alive: false
|
||||||
@@ -136,7 +147,6 @@ stdout_output:
|
|||||||
# $ openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem
|
# $ openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem
|
||||||
# $ cat certificate.pem key.pem > falco.pem
|
# $ cat certificate.pem key.pem > falco.pem
|
||||||
# $ sudo cp falco.pem /etc/falco/falco.pem
|
# $ sudo cp falco.pem /etc/falco/falco.pem
|
||||||
|
|
||||||
webserver:
|
webserver:
|
||||||
enabled: true
|
enabled: true
|
||||||
listen_port: 8765
|
listen_port: 8765
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ configure_file(debian/postinst.in debian/postinst)
|
|||||||
configure_file(debian/prerm.in debian/prerm)
|
configure_file(debian/prerm.in debian/prerm)
|
||||||
|
|
||||||
if(NOT SYSDIG_DIR)
|
if(NOT SYSDIG_DIR)
|
||||||
set(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig")
|
get_filename_component(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig" REALPATH)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
file(COPY "${PROJECT_SOURCE_DIR}/scripts/debian/falco"
|
file(COPY "${PROJECT_SOURCE_DIR}/scripts/debian/falco"
|
||||||
|
|||||||
1
test/.gitignore
vendored
1
test/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
falco_traces.yaml
|
|
||||||
@@ -40,6 +40,8 @@ class FalcoTest(Test):
|
|||||||
build_type = "debug" if build_type == "debug" else "release"
|
build_type = "debug" if build_type == "debug" else "release"
|
||||||
|
|
||||||
build_dir = os.path.join('/build', build_type)
|
build_dir = os.path.join('/build', build_type)
|
||||||
|
if not os.path.exists(build_dir):
|
||||||
|
build_dir = '../build'
|
||||||
self.falcodir = self.params.get('falcodir', '/', default=os.path.join(self.basedir, build_dir))
|
self.falcodir = self.params.get('falcodir', '/', default=os.path.join(self.basedir, build_dir))
|
||||||
|
|
||||||
self.stdout_is = self.params.get('stdout_is', '*', default='')
|
self.stdout_is = self.params.get('stdout_is', '*', default='')
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
if(NOT SYSDIG_DIR)
|
if(NOT SYSDIG_DIR)
|
||||||
set(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig")
|
get_filename_component(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig" REALPATH)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(FALCO_ENGINE_SOURCE_FILES
|
set(FALCO_ENGINE_SOURCE_FILES
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
if(NOT SYSDIG_DIR)
|
if(NOT SYSDIG_DIR)
|
||||||
set(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig")
|
get_filename_component(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig" REALPATH)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
configure_file("${SYSDIG_DIR}/userspace/sysdig/config_sysdig.h.in" config_sysdig.h)
|
configure_file("${SYSDIG_DIR}/userspace/sysdig/config_sysdig.h.in" config_sysdig.h)
|
||||||
@@ -27,6 +27,8 @@ add_executable(falco
|
|||||||
falco_outputs.cpp
|
falco_outputs.cpp
|
||||||
event_drops.cpp
|
event_drops.cpp
|
||||||
statsfilewriter.cpp
|
statsfilewriter.cpp
|
||||||
|
timer.cpp
|
||||||
|
module_utils.cpp
|
||||||
falco.cpp
|
falco.cpp
|
||||||
"${SYSDIG_DIR}/userspace/sysdig/fields_info.cpp"
|
"${SYSDIG_DIR}/userspace/sysdig/fields_info.cpp"
|
||||||
webserver.cpp)
|
webserver.cpp)
|
||||||
@@ -49,16 +51,11 @@ target_link_libraries(falco
|
|||||||
configure_file(config_falco.h.in config_falco.h)
|
configure_file(config_falco.h.in config_falco.h)
|
||||||
|
|
||||||
add_custom_command(TARGET falco
|
add_custom_command(TARGET falco
|
||||||
COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/verify_engine_fields.sh ${CMAKE_SOURCE_DIR}
|
COMMAND bash ${CMAKE_CURRENT_SOURCE_DIR}/verify_engine_fields ${CMAKE_SOURCE_DIR}
|
||||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
COMMENT "Comparing engine fields checksum in falco_engine.h to actual fields"
|
COMMENT "Comparing engine fields checksum in falco_engine.h to actual fields"
|
||||||
)
|
)
|
||||||
|
|
||||||
# add_custom_target(verify_engine_fields
|
|
||||||
# DEPENDS verify_engine_fields.sh falco_engine.h)
|
|
||||||
|
|
||||||
# add_dependencies(verify_engine_fields falco)
|
|
||||||
|
|
||||||
install(TARGETS falco DESTINATION ${FALCO_BIN_DIR})
|
install(TARGETS falco DESTINATION ${FALCO_BIN_DIR})
|
||||||
install(DIRECTORY lua
|
install(DIRECTORY lua
|
||||||
DESTINATION ${FALCO_SHARE_DIR}
|
DESTINATION ${FALCO_SHARE_DIR}
|
||||||
|
|||||||
@@ -27,4 +27,4 @@ limitations under the License.
|
|||||||
#define FALCO_INSTALL_CONF_FILE "/etc/falco/falco.yaml"
|
#define FALCO_INSTALL_CONF_FILE "/etc/falco/falco.yaml"
|
||||||
#define FALCO_SOURCE_LUA_DIR "${PROJECT_SOURCE_DIR}/userspace/falco/lua/"
|
#define FALCO_SOURCE_LUA_DIR "${PROJECT_SOURCE_DIR}/userspace/falco/lua/"
|
||||||
|
|
||||||
#define PROBE_NAME "${PROBE_NAME}"
|
#define PROBE_NAME "@PROBE_NAME@"
|
||||||
|
|||||||
@@ -220,6 +220,15 @@ void falco_configuration::init(string conf_filename, list<string> &cmdline_optio
|
|||||||
m_syscall_evt_drop_rate = m_config->get_scalar<double>("syscall_event_drops", "rate", 0.3333);
|
m_syscall_evt_drop_rate = m_config->get_scalar<double>("syscall_event_drops", "rate", 0.3333);
|
||||||
m_syscall_evt_drop_max_burst = m_config->get_scalar<double>("syscall_event_drops", "max_burst", 10);
|
m_syscall_evt_drop_max_burst = m_config->get_scalar<double>("syscall_event_drops", "max_burst", 10);
|
||||||
|
|
||||||
|
m_module_check_frequency = m_config->get_scalar<uint64_t>("module_check", "frequency", 10);
|
||||||
|
if(m_module_check_frequency < 10) {
|
||||||
|
throw invalid_argument("Module check frequency must be higher than 10 seconds");
|
||||||
|
}
|
||||||
|
m_module_check_max_consecutive_failures = m_config->get_scalar<int>("module_check", "max_consecutive_failures", 3);
|
||||||
|
m_module_check_backoff_max_attempts = m_config->get_scalar<int>("module_check", "backoff", "max_attempts", 5);
|
||||||
|
m_module_check_backoff_init_delay = m_config->get_scalar<uint64_t>("module_check", "backoff", "init_delay", 100);
|
||||||
|
m_module_check_backoff_max_delay = m_config->get_scalar<uint64_t>("module_check", "backoff", "max_delay", 3000);
|
||||||
|
|
||||||
m_syscall_evt_simulate_drops = m_config->get_scalar<bool>("syscall_event_drops", "simulate_drops", false);
|
m_syscall_evt_simulate_drops = m_config->get_scalar<bool>("syscall_event_drops", "simulate_drops", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -133,6 +133,47 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a scalar value defined inside a 3 level nested structure like:
|
||||||
|
* file_output:
|
||||||
|
* enabled: true
|
||||||
|
* filename: output_file.txt
|
||||||
|
*
|
||||||
|
* get_scalar<bool>("file_output", "enabled", false)
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
const T get_scalar(const std::string& key, const std::string& subkey, const std::string& subsubkey, const T& default_value)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto node = m_root[key][subkey][subsubkey];
|
||||||
|
if (node.IsDefined())
|
||||||
|
{
|
||||||
|
return node.as<T>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const YAML::BadConversion& ex)
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot read config file (" + m_path + "): wrong type at key " + key + "\n";
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return default_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the second-level node identified by key[key][subkey] to value.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
void set_scalar(const std::string& key, const std::string& subkey, const std::string& subsubkey, const T& value)
|
||||||
|
{
|
||||||
|
auto node = m_root;
|
||||||
|
if (node.IsDefined())
|
||||||
|
{
|
||||||
|
node[key][subkey][subsubkey] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// called with the last variadic arg (where the sequence is expected to be found)
|
// called with the last variadic arg (where the sequence is expected to be found)
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void get_sequence_from_node(T& ret, const YAML::Node &node)
|
void get_sequence_from_node(T& ret, const YAML::Node &node)
|
||||||
@@ -216,6 +257,12 @@ class falco_configuration
|
|||||||
double m_syscall_evt_drop_rate;
|
double m_syscall_evt_drop_rate;
|
||||||
double m_syscall_evt_drop_max_burst;
|
double m_syscall_evt_drop_max_burst;
|
||||||
|
|
||||||
|
uint64_t m_module_check_frequency;
|
||||||
|
int m_module_check_max_consecutive_failures;
|
||||||
|
int m_module_check_backoff_max_attempts;
|
||||||
|
uint64_t m_module_check_backoff_init_delay;
|
||||||
|
uint64_t m_module_check_backoff_max_delay;
|
||||||
|
|
||||||
// Only used for testing
|
// Only used for testing
|
||||||
bool m_syscall_evt_simulate_drops;
|
bool m_syscall_evt_simulate_drops;
|
||||||
|
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ limitations under the License.
|
|||||||
#include "config_falco.h"
|
#include "config_falco.h"
|
||||||
#include "statsfilewriter.h"
|
#include "statsfilewriter.h"
|
||||||
#include "webserver.h"
|
#include "webserver.h"
|
||||||
|
#include "timer.h"
|
||||||
|
#include "retry.h"
|
||||||
|
#include "module_utils.h"
|
||||||
|
|
||||||
typedef function<void(sinsp* inspector)> open_t;
|
typedef function<void(sinsp* inspector)> open_t;
|
||||||
|
|
||||||
@@ -228,6 +231,8 @@ uint64_t do_inspect(falco_engine *engine,
|
|||||||
string &stats_filename,
|
string &stats_filename,
|
||||||
uint64_t stats_interval,
|
uint64_t stats_interval,
|
||||||
bool all_events,
|
bool all_events,
|
||||||
|
bool verbose,
|
||||||
|
bool disable_syscall,
|
||||||
int &result)
|
int &result)
|
||||||
{
|
{
|
||||||
uint64_t num_evts = 0;
|
uint64_t num_evts = 0;
|
||||||
@@ -253,11 +258,42 @@ uint64_t do_inspect(falco_engine *engine,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Module check settings
|
||||||
|
utils::timer t;
|
||||||
|
t.reset();
|
||||||
|
|
||||||
|
uint64_t frequency = config.m_module_check_frequency;
|
||||||
|
auto num_failures = 0;
|
||||||
|
auto max_failures = config.m_module_check_max_consecutive_failures;
|
||||||
|
auto max_attempts = config.m_module_check_backoff_max_attempts;
|
||||||
|
auto ini_delay = config.m_module_check_backoff_init_delay;
|
||||||
|
auto max_delay = config.m_module_check_backoff_max_delay;
|
||||||
|
|
||||||
//
|
//
|
||||||
// Loop through the events
|
// Loop through the events
|
||||||
//
|
//
|
||||||
while(1)
|
while(true)
|
||||||
{
|
{
|
||||||
|
// Check module every x seconds
|
||||||
|
if(!disable_syscall && t.seconds_elapsed() > frequency)
|
||||||
|
{
|
||||||
|
// Check module is present and loaded with exponential backoff (eg., 100, 200, 400, ...)
|
||||||
|
// When module is missing or unloaded, try to insert it
|
||||||
|
// Retries at most <max_attempts> times
|
||||||
|
// Stops early if module is found
|
||||||
|
auto found = utils::retry(max_attempts, ini_delay, max_delay, utils::module_predicate, utils::has_module, verbose, true);
|
||||||
|
|
||||||
|
// Count how many intervals the module is missing, reset counter when module has been found
|
||||||
|
num_failures = found ? 0 : num_failures + 1;
|
||||||
|
// Stop falco if module is missing from <count * stop_after> checks
|
||||||
|
if (num_failures >= max_failures)
|
||||||
|
{
|
||||||
|
result = EXIT_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Reset timer
|
||||||
|
t.reset();
|
||||||
|
}
|
||||||
|
|
||||||
rc = inspector->next(&ev);
|
rc = inspector->next(&ev);
|
||||||
|
|
||||||
@@ -271,7 +307,7 @@ uint64_t do_inspect(falco_engine *engine,
|
|||||||
|
|
||||||
if (g_terminate || g_restart)
|
if (g_terminate || g_restart)
|
||||||
{
|
{
|
||||||
falco_logger::log(LOG_INFO, "SIGHUP Received, restarting...\n");
|
falco_logger::log(LOG_INFO, "SIGHUP received, restarting...\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if(rc == SCAP_TIMEOUT)
|
else if(rc == SCAP_TIMEOUT)
|
||||||
@@ -292,10 +328,11 @@ uint64_t do_inspect(falco_engine *engine,
|
|||||||
throw sinsp_exception(inspector->getlasterr().c_str());
|
throw sinsp_exception(inspector->getlasterr().c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (duration_start == 0)
|
if(duration_start == 0)
|
||||||
{
|
{
|
||||||
duration_start = ev->get_ts();
|
duration_start = ev->get_ts();
|
||||||
} else if(duration_to_tot_ns > 0)
|
}
|
||||||
|
else if(duration_to_tot_ns > 0)
|
||||||
{
|
{
|
||||||
if(ev->get_ts() - duration_start >= duration_to_tot_ns)
|
if(ev->get_ts() - duration_start >= duration_to_tot_ns)
|
||||||
{
|
{
|
||||||
@@ -1068,6 +1105,17 @@ int falco_init(int argc, char **argv)
|
|||||||
if (disable_k8s_audit) {
|
if (disable_k8s_audit) {
|
||||||
open_f = open_cb;
|
open_f = open_cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check that the kernel module is present at startup, otherwise try to add it
|
||||||
|
if(!utils::has_module(verbose, false))
|
||||||
|
{
|
||||||
|
falco_logger::log(LOG_ERR, "Module not found. Trying to load it ...\n");
|
||||||
|
if(!utils::ins_module())
|
||||||
|
{
|
||||||
|
result = EXIT_FAILURE;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1075,11 +1123,7 @@ int falco_init(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
catch(sinsp_exception &e)
|
catch(sinsp_exception &e)
|
||||||
{
|
{
|
||||||
if(system("modprobe " PROBE_NAME " > /dev/null 2> /dev/null"))
|
rethrow_exception(current_exception());
|
||||||
{
|
|
||||||
falco_logger::log(LOG_ERR, "Unable to load the driver. Exiting.\n");
|
|
||||||
}
|
|
||||||
open_f(inspector);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1170,9 +1214,7 @@ int falco_init(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint64_t num_evts;
|
uint64_t num_evts = do_inspect(engine,
|
||||||
|
|
||||||
num_evts = do_inspect(engine,
|
|
||||||
outputs,
|
outputs,
|
||||||
inspector,
|
inspector,
|
||||||
config,
|
config,
|
||||||
@@ -1181,6 +1223,8 @@ int falco_init(int argc, char **argv)
|
|||||||
stats_filename,
|
stats_filename,
|
||||||
stats_interval,
|
stats_interval,
|
||||||
all_events,
|
all_events,
|
||||||
|
verbose,
|
||||||
|
disable_syscall,
|
||||||
result);
|
result);
|
||||||
|
|
||||||
duration = ((double)clock()) / CLOCKS_PER_SEC - duration;
|
duration = ((double)clock()) / CLOCKS_PER_SEC - duration;
|
||||||
@@ -1189,11 +1233,11 @@ int falco_init(int argc, char **argv)
|
|||||||
|
|
||||||
if(verbose)
|
if(verbose)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Driver Events:%" PRIu64 "\nDriver Drops:%" PRIu64 "\n",
|
fprintf(stdout, "Driver events: %" PRIu64 "\nDriver drops: %" PRIu64 "\n",
|
||||||
cstats.n_evts,
|
cstats.n_evts,
|
||||||
cstats.n_drops);
|
cstats.n_drops);
|
||||||
|
|
||||||
fprintf(stderr, "Elapsed time: %.3lf, Captured Events: %" PRIu64 ", %.2lf eps\n",
|
fprintf(stdout, "Elapsed time: %.3lf\nCaptured events: %" PRIu64 "\nEps: %.2lf\n",
|
||||||
duration,
|
duration,
|
||||||
num_evts,
|
num_evts,
|
||||||
num_evts / duration);
|
num_evts / duration);
|
||||||
|
|||||||
120
userspace/falco/module_utils.cpp
Normal file
120
userspace/falco/module_utils.cpp
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2016-2019 Draios Inc dba Sysdig.
|
||||||
|
|
||||||
|
This file is part of falco.
|
||||||
|
|
||||||
|
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 "config_falco.h"
|
||||||
|
#include "logger.h"
|
||||||
|
#include "module_utils.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
|
||||||
|
bool has_module(bool verbose, bool strict)
|
||||||
|
{
|
||||||
|
// Comparing considering underscores (95) equal to dashes (45), and viceversa
|
||||||
|
std::function<bool(const char &, const char &)> comparator = [](const char &a, const char &b) {
|
||||||
|
return a == b || (a == 45 && b == 95) || (b == 95 && a == 45);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ifstream modules(db);
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
while(std::getline(modules, line))
|
||||||
|
{
|
||||||
|
bool shorter = module.length() <= line.length();
|
||||||
|
if(shorter && std::equal(module.begin(), module.end(), line.begin(), comparator))
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
if(!strict)
|
||||||
|
{
|
||||||
|
falco_logger::log(LOG_INFO, "Kernel module found: true (not strict)\n");
|
||||||
|
modules.close();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istringstream iss(line);
|
||||||
|
std::vector<std::string> cols(std::istream_iterator<std::string>{iss}, std::istream_iterator<std::string>());
|
||||||
|
|
||||||
|
// Check the module's number of instances - ie., whether it is loaded or not
|
||||||
|
auto ninstances = cols.at(2);
|
||||||
|
result = result && std::stoi(ninstances) > 0;
|
||||||
|
|
||||||
|
// Check the module's load state
|
||||||
|
auto state = cols.at(4);
|
||||||
|
std::transform(state.begin(), state.end(), state.begin(), ::tolower);
|
||||||
|
result = result && (state == module_state_live);
|
||||||
|
|
||||||
|
if(verbose)
|
||||||
|
{
|
||||||
|
falco_logger::log(LOG_INFO, "Kernel module instances: " + ninstances + "\n");
|
||||||
|
falco_logger::log(LOG_INFO, "Kernel module load state: " + state + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the module's taint state
|
||||||
|
if(cols.size() > 6)
|
||||||
|
{
|
||||||
|
auto taint = cols.at(6);
|
||||||
|
auto died = taint.find(taint_die) != std::string::npos;
|
||||||
|
auto warn = taint.find(taint_warn) != std::string::npos;
|
||||||
|
auto unloaded = taint.find(taint_forced_rmmod) != std::string::npos;
|
||||||
|
result = result && !died && !warn && !unloaded;
|
||||||
|
|
||||||
|
if(verbose)
|
||||||
|
{
|
||||||
|
taint.erase(0, taint.find_first_not_of('('));
|
||||||
|
taint.erase(taint.find_last_not_of(')') + 1);
|
||||||
|
falco_logger::log(LOG_INFO, "Kernel module taint state: " + taint + "\n");
|
||||||
|
std::ostringstream message;
|
||||||
|
message << std::boolalpha << "Kernel module presence: " << result << "\n";
|
||||||
|
falco_logger::log(LOG_INFO, message.str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modules.close();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
modules.close();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ins_module()
|
||||||
|
{
|
||||||
|
if(system("modprobe " PROBE_NAME " > /dev/null 2> /dev/null"))
|
||||||
|
{
|
||||||
|
// todo > fallback to a custom directory where to look for the module using `modprobe -d build/driver`
|
||||||
|
falco_logger::log(LOG_ERR, "Unable to load the module.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool module_predicate(bool has_module)
|
||||||
|
{
|
||||||
|
if(has_module)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Retry only when we have been not able to insert the module
|
||||||
|
return !ins_module();
|
||||||
|
}
|
||||||
|
} // namespace utils
|
||||||
37
userspace/falco/module_utils.h
Normal file
37
userspace/falco/module_utils.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2016-2019 Draios Inc dba Sysdig.
|
||||||
|
|
||||||
|
This file is part of falco.
|
||||||
|
|
||||||
|
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 <string>
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
const std::string db("/proc/modules");
|
||||||
|
const std::string module(PROBE_NAME);
|
||||||
|
const std::string module_state_live("live");
|
||||||
|
// Module's taint state constants
|
||||||
|
// see: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/kernel/panic.c#n351
|
||||||
|
const std::string taint_die("D");
|
||||||
|
const std::string taint_forced_rmmod("R");
|
||||||
|
const std::string taint_warn("W");
|
||||||
|
bool has_module(bool verbose, bool strict);
|
||||||
|
bool ins_module();
|
||||||
|
bool module_predicate(bool has_module);
|
||||||
|
} // namespace utils
|
||||||
85
userspace/falco/retry.h
Normal file
85
userspace/falco/retry.h
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2016-2019 Draios Inc dba Sysdig.
|
||||||
|
|
||||||
|
This file is part of falco.
|
||||||
|
|
||||||
|
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 "logger.h"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <chrono>
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#if __cplusplus < 201402L
|
||||||
|
template< class T >
|
||||||
|
using decay_t = typename decay<T>::type;
|
||||||
|
|
||||||
|
template< bool B, class T = void >
|
||||||
|
using enable_if_t = typename enable_if<B,T>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __cplusplus != 201402L || __cplusplus != 201703L
|
||||||
|
template< class F, class... ArgTypes>
|
||||||
|
using result_of_t = typename result_of<F, ArgTypes...>::type;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
template<
|
||||||
|
typename Predicate,
|
||||||
|
typename Callable,
|
||||||
|
typename... Args,
|
||||||
|
// figure out the callable return type
|
||||||
|
typename R = decay_t<result_of_t<Callable &(Args...)>>,
|
||||||
|
// require that Predicate is actually a Predicate
|
||||||
|
enable_if_t<std::is_convertible<result_of_t<Predicate &(R)>, bool>::value, int> = 0>
|
||||||
|
R retry(int max_retries,
|
||||||
|
uint64_t initial_delay_ms,
|
||||||
|
uint64_t max_backoff_ms,
|
||||||
|
Predicate &&retriable,
|
||||||
|
Callable &&callable,
|
||||||
|
Args &&... args)
|
||||||
|
{
|
||||||
|
int retries = 0;
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
falco_logger::log(LOG_INFO, "Retry no.: " + std::to_string(retries) + "\n");
|
||||||
|
bool result = callable(std::forward<Args>(args)...);
|
||||||
|
|
||||||
|
if(!retriable(result))
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
if(retries >= max_retries)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
int64_t delay = 0;
|
||||||
|
if(initial_delay_ms > 0)
|
||||||
|
{
|
||||||
|
delay = std::min(initial_delay_ms << retries, max_backoff_ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostringstream message;
|
||||||
|
message << "Waiting " << delay << "ms ... \n";
|
||||||
|
falco_logger::log(LOG_INFO, message.str());
|
||||||
|
// Blocking for `delay` ms
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
|
||||||
|
retries++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
userspace/falco/timer.cpp
Normal file
34
userspace/falco/timer.cpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2016-2019 Draios Inc dba Sysdig.
|
||||||
|
|
||||||
|
This file is part of falco.
|
||||||
|
|
||||||
|
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 "timer.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
void timer::reset()
|
||||||
|
{
|
||||||
|
start = clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long long timer::seconds_elapsed() const
|
||||||
|
{
|
||||||
|
return std::chrono::duration_cast<seconds>(clock::now() - start).count();
|
||||||
|
}
|
||||||
|
} // namespace utils
|
||||||
37
userspace/falco/timer.h
Normal file
37
userspace/falco/timer.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2016-2019 Draios Inc dba Sysdig.
|
||||||
|
|
||||||
|
This file is part of falco.
|
||||||
|
|
||||||
|
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 "logger.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
namespace utils
|
||||||
|
{
|
||||||
|
struct timer
|
||||||
|
{
|
||||||
|
typedef std::chrono::steady_clock clock;
|
||||||
|
typedef std::chrono::seconds seconds;
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
unsigned long long seconds_elapsed() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
clock::time_point start;
|
||||||
|
};
|
||||||
|
} // namespace utils
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/sh
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
set -euo pipefail
|
set -eu -o pipefail
|
||||||
|
|
||||||
SOURCE_DIR=$1
|
SOURCE_DIR=$1
|
||||||
OPENSSL=../../openssl-prefix/src/openssl/target/bin/openssl
|
OPENSSL=../../openssl-prefix/src/openssl/target/bin/openssl
|
||||||
@@ -11,13 +11,13 @@ if ! command -v ${OPENSSL} version > /dev/null 2>&1; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
NEW_CHECKSUM=$(./falco --list -N | ${OPENSSL} dgst -sha256 | awk '{print $2}')
|
NEW_CHECKSUM=$(./falco --list -N | ${OPENSSL} dgst -sha256 | awk '{print $2}')
|
||||||
CUR_CHECKSUM=$(grep FALCO_FIELDS_CHECKSUM ${SOURCE_DIR}/userspace/engine/falco_engine_version.h | awk '{print $3}' | sed -e 's/"//g')
|
CUR_CHECKSUM=$(grep FALCO_FIELDS_CHECKSUM "${SOURCE_DIR}/userspace/engine/falco_engine_version.h" | awk '{print $3}' | sed -e 's/"//g')
|
||||||
|
|
||||||
|
|
||||||
if [ $NEW_CHECKSUM != $CUR_CHECKSUM ]; then
|
if [ "$NEW_CHECKSUM" != "$CUR_CHECKSUM" ]; then
|
||||||
echo "Set of fields supported by falco/sysdig libraries has changed (new checksum $NEW_CHECKSUM != old checksum $CUR_CHECKSUM)."
|
echo "Set of fields supported by falco/sysdig libraries has changed (new checksum $NEW_CHECKSUM != old checksum $CUR_CHECKSUM)."
|
||||||
echo "Update checksum and/or version in falco_engine_version.h."
|
echo "Update checksum and/or version in falco_engine_version.h."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exit 0
|
exit 0
|
||||||
@@ -175,12 +175,6 @@ void falco_webserver::init(falco_configuration *config,
|
|||||||
m_outputs = outputs;
|
m_outputs = outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename ...Args>
|
|
||||||
std::unique_ptr<T> make_unique( Args&& ...args )
|
|
||||||
{
|
|
||||||
return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
void falco_webserver::start()
|
void falco_webserver::start()
|
||||||
{
|
{
|
||||||
if(m_server)
|
if(m_server)
|
||||||
|
|||||||
@@ -25,6 +25,14 @@ limitations under the License.
|
|||||||
#include "falco_engine.h"
|
#include "falco_engine.h"
|
||||||
#include "falco_outputs.h"
|
#include "falco_outputs.h"
|
||||||
|
|
||||||
|
#if __cplusplus < 201402L
|
||||||
|
template<typename T, typename... Ts>
|
||||||
|
std::unique_ptr<T> make_unique(Ts&&... params)
|
||||||
|
{
|
||||||
|
return std::unique_ptr<T>(new T(std::forward<Ts>(params)...));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
class k8s_audit_handler : public CivetHandler
|
class k8s_audit_handler : public CivetHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|||||||
Reference in New Issue
Block a user