From 7056cb90352c416b54d1a0c9fd8479681db7db4f Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Fri, 17 Nov 2023 16:37:10 +0100 Subject: [PATCH] chore(userspace): properly let old config keys override new ones when set to a non-default value. Signed-off-by: Federico Di Pierro Co-authored-by: Andrea Terzolo --- falco.yaml | 89 +++++++++++++++---------------- userspace/falco/configuration.cpp | 53 +++++++++++------- 2 files changed, 77 insertions(+), 65 deletions(-) diff --git a/falco.yaml b/falco.yaml index 069d1cda..cde3bbe4 100644 --- a/falco.yaml +++ b/falco.yaml @@ -27,6 +27,8 @@ # (Falco environment variables) # Falco rules files # rules_file +# Falco engine +# engine # Falco plugins # load_plugins # plugins @@ -62,8 +64,6 @@ # syscall_event_timeouts # syscall_event_drops # metrics -# Falco engine -# engine # Falco performance tuning (advanced) # syscall_buf_size_preset # syscall_drop_failed_exit @@ -147,6 +147,48 @@ rules_file: - /etc/falco/falco_rules.local.yaml - /etc/falco/rules.d +################ +# Falco engine # +################ + +# [Stable] `engine` +# +# --- [Description] +# +# Falco supports different engines to generate events. +# Choose the appropriate engine kind based on your system's configuration and requirements. +# +# Available engines: +# - `kmod`: Kernel Module (Kernel Module) +# - `ebpf`: eBPF (Extended Berkeley Packet Filter) +# - `modern-ebpf`: Modern eBPF (Modern Extended Berkeley Packet Filter), available only for recent kernels +# - `gvisor`: gVisor (gVisor sandbox) +# - `replay`: Replay a scap trace file +# - `none`: No engine loaded, useful to run `syscall` source plugin or just plugins without loading any other event producer. + +# Select the appropriate engine kind by uncommenting the corresponding line. +# Make sure to specify only one engine kind at a time. +# Moreover, for each engine multiple options might be available, +# grouped under engine specific configuration keys. +engine: + kind: kmod + kmod: + buf_size_preset: 4 # Overridden by deprecated syscall_buf_size_preset if set + drop_failed_exit: false # Overridden by deprecated syscall_drop_failed_exit if set + ebpf: + probe: /path/to/probe.o + buf_size_preset: 4 # Overridden by deprecated syscall_buf_size_preset if set + drop_failed_exit: false # Overridden by deprecated syscall_drop_failed_exit if set + modern-ebpf: + cpus_for_each_syscall_buffer: 2 # Overridden by deprecated cpus_for_each_syscall_buffer if set + buf_size_preset: 4 # Overridden by deprecated syscall_buf_size_preset if set + drop_failed_exit: false # Overridden by deprecated syscall_drop_failed_exit if set + replay: + trace_file: /path/to/file.scap + gvisor: + config: /path/to/gvisor.yaml + root: /gvisor/root + ################# # Falco plugins # ################# @@ -771,49 +813,6 @@ metrics: convert_memory_to_mb: true include_empty_values: false -################ -# Falco engine # -################ - -# [Stable] `engine` -# -# --- [Description] -# -# Falco supports different engines to generate events. -# Choose the appropriate engine kind based on your system's configuration and requirements. -# -# Available engines: -# - `kmod`: Kernel Module (Kernel Module) -# - `ebpf`: eBPF (Extended Berkeley Packet Filter) -# - `modern-ebpf`: Modern eBPF (Modern Extended Berkeley Packet Filter), available only for recent kernels -# - `gvisor`: gVisor (gVisor sandbox) -# - `replay`: Replay a scap trace file -# - `none`: No engine loaded, useful to run `syscall` source plugin or just plugins without loading any other event producer. - -# Select the appropriate engine kind by uncommenting the corresponding line. -# Make sure to specify only one engine kind at a time. -# Moreover, for each engine multiple options might be available, -# grouped under the `engine.kind` configuration key. - -engine: - kind: kmod - kmod: - buf_size_preset: 4 # Overridden by deprecated syscall_buf_size_preset - drop_failed_exit: false # Overridden by deprecated syscall_drop_failed_exit - ebpf: - probe: /path/to/probe.o - buf_size_preset: 4 # Overridden by deprecated syscall_buf_size_preset - drop_failed_exit: false # Overridden by deprecated syscall_drop_failed_exit - modern-ebpf: - cpus_for_each_syscall_buffer: 2 # Overridden by deprecated cpus_for_each_syscall_buffer - buf_size_preset: 4 # Overridden by deprecated syscall_buf_size_preset - drop_failed_exit: false # Overridden by deprecated syscall_drop_failed_exit - replay: - trace_file: /path/to/file.scap - gvisor: - config: /path/to/gvisor.yaml - root: /gvisor/root - ####################################### # Falco performance tuning (advanced) # ####################################### diff --git a/userspace/falco/configuration.cpp b/userspace/falco/configuration.cpp index af0e45f8..f728f7c3 100644 --- a/userspace/falco/configuration.cpp +++ b/userspace/falco/configuration.cpp @@ -114,6 +114,10 @@ void falco_configuration::load_engine_config(const std::string& config_name, con {"none",engine_kind_t::NONE}, }; + constexpr int default_buf_size_preset = 4; + constexpr int default_cpus_for_each_syscall_buffer = 2; + constexpr bool default_drop_failed = false; + auto driver_mode_str = config.get_scalar("engine.kind", "kmod"); if (engine_mode_lut.find(driver_mode_str) != engine_mode_lut.end()) { @@ -127,21 +131,21 @@ void falco_configuration::load_engine_config(const std::string& config_name, con switch (m_engine_mode) { case engine_kind_t::KMOD: - m_kmod.m_buf_size_preset = config.get_scalar("engine.kmod.buf_size_preset", 4); - m_kmod.m_drop_failed_exit = config.get_scalar("engine.kmod.drop_failed", false); + m_kmod.m_buf_size_preset = config.get_scalar("engine.kmod.buf_size_preset", default_buf_size_preset); + m_kmod.m_drop_failed_exit = config.get_scalar("engine.kmod.drop_failed", default_drop_failed); break; case engine_kind_t::EBPF: // TODO: default value for `probe` should be $HOME/FALCO_PROBE_BPF_FILEPATH, // to be done once we drop the CLI option otherwise we would need to make the check twice, // once here, and once when we merge the CLI options in the config file. m_ebpf.m_probe_path = config.get_scalar("engine.ebpf.probe", ""); - m_ebpf.m_buf_size_preset = config.get_scalar("engine.ebpf.buf_size_preset", 4); - m_ebpf.m_drop_failed_exit = config.get_scalar("engine.ebpf.drop_failed", false); + m_ebpf.m_buf_size_preset = config.get_scalar("engine.ebpf.buf_size_preset", default_buf_size_preset); + m_ebpf.m_drop_failed_exit = config.get_scalar("engine.ebpf.drop_failed", default_drop_failed); break; case engine_kind_t::MODERN_EBPF: - m_modern_ebpf.m_cpus_for_each_syscall_buffer = config.get_scalar("engine.modern-ebpf.cpus_for_each_syscall_buffer", 2); - m_modern_ebpf.m_buf_size_preset = config.get_scalar("engine.modern-ebpf.buf_size_preset", 4); - m_modern_ebpf.m_drop_failed_exit = config.get_scalar("engine.modern-ebpf.drop_failed", false); + m_modern_ebpf.m_cpus_for_each_syscall_buffer = config.get_scalar("engine.modern-ebpf.cpus_for_each_syscall_buffer", default_cpus_for_each_syscall_buffer); + m_modern_ebpf.m_buf_size_preset = config.get_scalar("engine.modern-ebpf.buf_size_preset", default_buf_size_preset); + m_modern_ebpf.m_drop_failed_exit = config.get_scalar("engine.modern-ebpf.drop_failed", default_drop_failed); break; case engine_kind_t::REPLAY: m_replay.m_trace_file = config.get_scalar("engine.replay.trace_file", ""); @@ -162,6 +166,28 @@ void falco_configuration::load_engine_config(const std::string& config_name, con default: break; } + + // TODO: remove in Falco 0.38 since they are deprecated. + // old config keys always have priority over new ones, when set to a non-default value + auto buf_size_preset = config.get_scalar("syscall_buf_size_preset", default_buf_size_preset); + if (buf_size_preset != default_buf_size_preset) + { + m_kmod.m_buf_size_preset = buf_size_preset; + m_ebpf.m_buf_size_preset = buf_size_preset; + m_modern_ebpf.m_buf_size_preset = buf_size_preset; + } + auto cpus_for_syscall_buffer = config.get_scalar("modern_bpf.cpus_for_each_syscall_buffer", default_cpus_for_each_syscall_buffer); + if (cpus_for_syscall_buffer != default_cpus_for_each_syscall_buffer) + { + m_modern_ebpf.m_cpus_for_each_syscall_buffer = cpus_for_syscall_buffer; + } + auto drop_failed = config.get_scalar("syscall_drop_failed_exit", default_drop_failed); + if (drop_failed) + { + m_kmod.m_drop_failed_exit = drop_failed; + m_ebpf.m_drop_failed_exit = drop_failed; + m_modern_ebpf.m_drop_failed_exit = drop_failed; + } } void falco_configuration::load_yaml(const std::string& config_name, const yaml_helper& config) @@ -423,18 +449,6 @@ void falco_configuration::load_yaml(const std::string& config_name, const yaml_h throw std::logic_error("Error reading config file(" + config_name + "): the maximum consecutive timeouts without an event must be an unsigned integer > 0"); } - /* We put this value in the configuration file because in this way we can change the dimension at every reload. - * The default value is `4` -> 8 MB. - */ - // TODO: remove in Falco 0.38 since they are deprecated. - m_kmod.m_buf_size_preset = config.get_scalar("syscall_buf_size_preset", 4); - m_ebpf.m_buf_size_preset = config.get_scalar("syscall_buf_size_preset", 4); - m_modern_ebpf.m_buf_size_preset = config.get_scalar("syscall_buf_size_preset", 4); - m_modern_ebpf.m_cpus_for_each_syscall_buffer = config.get_scalar("modern_bpf.cpus_for_each_syscall_buffer", 2); - m_kmod.m_drop_failed_exit = config.get_scalar("syscall_drop_failed_exit", false); - m_ebpf.m_drop_failed_exit = config.get_scalar("syscall_drop_failed_exit", false); - m_modern_ebpf.m_drop_failed_exit = config.get_scalar("syscall_drop_failed_exit", false); - m_base_syscalls_custom_set.clear(); config.get_sequence>(m_base_syscalls_custom_set, std::string("base_syscalls.custom_set")); m_base_syscalls_repair = config.get_scalar("base_syscalls.repair", false); @@ -453,7 +467,6 @@ void falco_configuration::load_yaml(const std::string& config_name, const yaml_h std::vector load_plugins; bool load_plugins_node_defined = config.is_defined("load_plugins"); - config.get_sequence>(load_plugins, "load_plugins"); std::list plugins;