Compare commits

...

26 Commits

Author SHA1 Message Date
Lorenzo Fontana
f1d676f949 new(userspace/falco): constants and header file for utils module
Signed-off-by: Lorenzo Fontana <lo@linux.com>
Co-Authored-By: Leonardo Di Donato <leodidonato@gmail.com>
Signed-off-by: Lorenzo Fontana <lo@linux.com>
2019-08-30 11:51:15 +02:00
Leonardo Di Donato
73f70cd0ef fix(usperspace): close modules files before leaving scope
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-30 08:45:32 +00:00
Leonardo Di Donato
b1edc405c2 update: check mmodule only when syscall source is enabled
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-30 08:39:52 +00:00
Leonardo Di Donato
efe39b4360 update(userspace): polyfill helper types (_t) for c++11
Co-authored-by: Lorenzo Fontana <lo@linux.com>
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-30 08:37:47 +00:00
Leonardo Di Donato
a04ac1def3 build: using c++11 standard
Co-authored-by: Lorenzo Fontana <lo@linux.com>

Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-30 08:34:38 +00:00
Leonardo Di Donato
f710edcde2 wip(userspace): checking module using event timestamps rather than an external timer
This approach does not sound good to me since events can miss
timestamps.

Furthermore logically it is wrong to check the module sends event using
the events ...

Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-30 08:32:43 +00:00
Leonardo Di Donato
7a3d5c62a0 docs: configuration opts for kernel module check
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:37 +00:00
Leonardo Di Donato
435a3b01db fix: improvements to the gitignore for integration tests
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:37 +00:00
Leonardo Di Donato
acd3e7f23a fix: check module in main loop
This way it will be able to detect events (and signals etc).
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:37 +00:00
Leonardo Di Donato
deaae756c0 new: helper to insert module
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:37 +00:00
Leonardo Di Donato
5a6c7af0c5 new: make backoff maximum wait per run configurable
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:37 +00:00
Leonardo Di Donato
05565f3524 update: minimum frequency for module check
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:37 +00:00
Leonardo Di Donato
980fb2f3a9 new: read module check configs
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:37 +00:00
Leonardo Di Donato
ba5e59964d new: method to grab nested (3 levels) configs
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:37 +00:00
Leonardo Di Donato
60721d52cb new: default falco config for module checking
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:36 +00:00
Leonardo Di Donato
8d9f88d45a new: lively check module every x seconds
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:36 +00:00
Leonardo Di Donato
4c04821d48 chore: bash improvements to engine fields verifier
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:36 +00:00
Leonardo Di Donato
fc2c1ac6cb new: generic exponential backoff helper
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:36 +00:00
Leonardo Di Donato
295c7afc32 new: helper to check module is inserted and loaded
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:36 +00:00
Leonardo Di Donato
f10b170174 new: timer
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:36 +00:00
Leonardo Di Donato
9f9d0e751b fix: remove polyfill for make_unique
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:36 +00:00
Leonardo Di Donato
322a2cdd25 build: get SYSDIG_DIR realpath
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:36 +00:00
Leonardo Di Donato
5c5c2e3309 build: compile usinf the 2014 ISO C++ standard
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:36 +00:00
Leonardo Di Donato
71832bc3ad new: explicitly check module is present at startup
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:43:35 +00:00
Leonardo Di Donato
93a3d14c41 fix(userspace): re-throw exceptions coming from sinsp
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:40:54 +00:00
Leonardo Di Donato
c7e7a868ed build: set SYSDIG_DIR to its real path
Signed-off-by: Leonardo Di Donato <leodidonato@gmail.com>
2019-08-29 10:29:41 +00:00
20 changed files with 468 additions and 43 deletions

2
.gitignore vendored
View File

@@ -3,10 +3,12 @@
*.pyc
test/falco_tests.yaml
test/falco_traces.yaml
test/traces-negative
test/traces-positive
test/traces-info
test/job-results
test/build
test/.phoronix-test-suite
test/results*.json.*
test/build

View File

@@ -20,7 +20,7 @@ cmake_minimum_required(VERSION 3.3.2)
project(falco)
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()
# Custom CMake modules
@@ -53,7 +53,7 @@ if(BUILD_WARNINGS_AS_ERRORS)
endif()
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_CXX_FLAGS_DEBUG "${DRAIOS_DEBUG_FLAGS}")

View File

@@ -80,7 +80,6 @@ buffered_outputs: false
# The rate at which log/alert messages are emitted is governed by a
# token bucket. The rate corresponds to one message every 30 seconds
# with a burst of 10 messages.
syscall_event_drops:
actions:
- log
@@ -88,6 +87,21 @@ syscall_event_drops:
rate: .03333
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
# rate of falco notifications. This throttling is controlled by the following configuration
# options:
@@ -99,14 +113,12 @@ syscall_event_drops:
# an initial quiet period, and then up to 1 notification per second
# afterward. It would gain the full burst back after 1000 seconds of
# no activity.
outputs:
rate: 1
max_burst: 1000
# Where security notifications should go.
# Multiple outputs can be enabled.
syslog_output:
enabled: true
@@ -117,7 +129,6 @@ syslog_output:
#
# Also, the file will be closed and reopened if falco is signaled with
# SIGUSR1.
file_output:
enabled: 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
# $ cat certificate.pem key.pem > falco.pem
# $ sudo cp falco.pem /etc/falco/falco.pem
webserver:
enabled: true
listen_port: 8765

View File

@@ -19,7 +19,7 @@ configure_file(debian/postinst.in debian/postinst)
configure_file(debian/prerm.in debian/prerm)
if(NOT SYSDIG_DIR)
set(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig")
get_filename_component(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig" REALPATH)
endif()
file(COPY "${PROJECT_SOURCE_DIR}/scripts/debian/falco"

1
test/.gitignore vendored
View File

@@ -1 +0,0 @@
falco_traces.yaml

View File

@@ -40,6 +40,8 @@ class FalcoTest(Test):
build_type = "debug" if build_type == "debug" else "release"
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.stdout_is = self.params.get('stdout_is', '*', default='')

View File

@@ -16,7 +16,7 @@
# limitations under the License.
if(NOT SYSDIG_DIR)
set(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig")
get_filename_component(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig" REALPATH)
endif()
set(FALCO_ENGINE_SOURCE_FILES

View File

@@ -16,7 +16,7 @@
# limitations under the License.
#
if(NOT SYSDIG_DIR)
set(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig")
get_filename_component(SYSDIG_DIR "${PROJECT_SOURCE_DIR}/../sysdig" REALPATH)
endif()
configure_file("${SYSDIG_DIR}/userspace/sysdig/config_sysdig.h.in" config_sysdig.h)
@@ -27,6 +27,8 @@ add_executable(falco
falco_outputs.cpp
event_drops.cpp
statsfilewriter.cpp
timer.cpp
module_utils.cpp
falco.cpp
"${SYSDIG_DIR}/userspace/sysdig/fields_info.cpp"
webserver.cpp)
@@ -49,16 +51,11 @@ target_link_libraries(falco
configure_file(config_falco.h.in config_falco.h)
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}
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(DIRECTORY lua
DESTINATION ${FALCO_SHARE_DIR}

View File

@@ -27,4 +27,4 @@ limitations under the License.
#define FALCO_INSTALL_CONF_FILE "/etc/falco/falco.yaml"
#define FALCO_SOURCE_LUA_DIR "${PROJECT_SOURCE_DIR}/userspace/falco/lua/"
#define PROBE_NAME "${PROBE_NAME}"
#define PROBE_NAME "@PROBE_NAME@"

View File

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

View File

@@ -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)
template <typename T>
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_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
bool m_syscall_evt_simulate_drops;

View File

@@ -47,6 +47,9 @@ limitations under the License.
#include "config_falco.h"
#include "statsfilewriter.h"
#include "webserver.h"
#include "timer.h"
#include "retry.h"
#include "module_utils.h"
typedef function<void(sinsp* inspector)> open_t;
@@ -228,6 +231,8 @@ uint64_t do_inspect(falco_engine *engine,
string &stats_filename,
uint64_t stats_interval,
bool all_events,
bool verbose,
bool disable_syscall,
int &result)
{
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
//
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);
@@ -271,7 +307,7 @@ uint64_t do_inspect(falco_engine *engine,
if (g_terminate || g_restart)
{
falco_logger::log(LOG_INFO, "SIGHUP Received, restarting...\n");
falco_logger::log(LOG_INFO, "SIGHUP received, restarting...\n");
break;
}
else if(rc == SCAP_TIMEOUT)
@@ -292,10 +328,11 @@ uint64_t do_inspect(falco_engine *engine,
throw sinsp_exception(inspector->getlasterr().c_str());
}
if (duration_start == 0)
if(duration_start == 0)
{
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)
{
@@ -1068,6 +1105,17 @@ int falco_init(int argc, char **argv)
if (disable_k8s_audit) {
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
{
@@ -1075,11 +1123,7 @@ int falco_init(int argc, char **argv)
}
catch(sinsp_exception &e)
{
if(system("modprobe " PROBE_NAME " > /dev/null 2> /dev/null"))
{
falco_logger::log(LOG_ERR, "Unable to load the driver. Exiting.\n");
}
open_f(inspector);
rethrow_exception(current_exception());
}
}
@@ -1170,9 +1214,7 @@ int falco_init(int argc, char **argv)
}
else
{
uint64_t num_evts;
num_evts = do_inspect(engine,
uint64_t num_evts = do_inspect(engine,
outputs,
inspector,
config,
@@ -1181,6 +1223,8 @@ int falco_init(int argc, char **argv)
stats_filename,
stats_interval,
all_events,
verbose,
disable_syscall,
result);
duration = ((double)clock()) / CLOCKS_PER_SEC - duration;
@@ -1189,11 +1233,11 @@ int falco_init(int argc, char **argv)
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_drops);
fprintf(stderr, "Elapsed time: %.3lf, Captured Events: %" PRIu64 ", %.2lf eps\n",
fprintf(stdout, "Elapsed time: %.3lf\nCaptured events: %" PRIu64 "\nEps: %.2lf\n",
duration,
num_evts,
num_evts / duration);

View 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

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

View File

@@ -1,6 +1,6 @@
#!/bin/sh
#!/usr/bin/env bash
set -euo pipefail
set -eu -o pipefail
SOURCE_DIR=$1
OPENSSL=../../openssl-prefix/src/openssl/target/bin/openssl
@@ -11,13 +11,13 @@ if ! command -v ${OPENSSL} version > /dev/null 2>&1; then
fi
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 "Update checksum and/or version in falco_engine_version.h."
exit 1
fi
exit 0
exit 0

View File

@@ -175,12 +175,6 @@ void falco_webserver::init(falco_configuration *config,
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()
{
if(m_server)

View File

@@ -25,6 +25,14 @@ limitations under the License.
#include "falco_engine.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
{
public: