diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2dbfad0e74f..c81120326c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: git_ref: ${{ github.event.pull_request.head.sha }} minimal: false build_type: Debug - cmd: "echo $(build/userspace/falco/falco -c ./falco.yaml --version | grep 'Engine:' | awk '{print $2}') $(echo $(build/userspace/falco/falco -c ./falco.yaml --version | grep 'Schema version:' | awk '{print $3}') $(build/userspace/falco/falco -c ./falco.yaml --list --markdown | grep '^`' | sort) $(build/userspace/falco/falco -c ./falco.yaml --list-syscall-events | sort) | sha256sum)" + cmd: "echo $(build/userspace/falco/falco -c ./falco.yaml --version | grep 'Engine:' | awk '{print $2}') $(echo $(build/userspace/falco/falco -c ./falco.yaml --version | grep 'Schema version:' | awk '{print $3}') $(build/userspace/falco/falco -c ./falco.yaml --list --markdown | grep '^`' | sort) $(build/userspace/falco/falco -c ./falco.yaml --list-events | sort) | sha256sum)" # checks the falco engine checksum for consistency check-engine-checksum: diff --git a/userspace/engine/falco_engine_version.h b/userspace/engine/falco_engine_version.h index 95c72a9e686..f3937071cfc 100644 --- a/userspace/engine/falco_engine_version.h +++ b/userspace/engine/falco_engine_version.h @@ -15,12 +15,12 @@ limitations under the License. */ // The version of this Falco engine. -#define FALCO_ENGINE_VERSION (25) +#define FALCO_ENGINE_VERSION (26) // This is the result of running the following command: // FALCO="falco -c ./falco.yaml" -// echo $($FALCO --version | grep 'Engine:' | awk '{print $2}') $(echo $($FALCO --version | grep 'Schema version:' | awk '{print $3}') $($FALCO --list --markdown | grep '^`' | sort) $($FALCO --list-syscall-events | sort) | sha256sum) +// echo $($FALCO --version | grep 'Engine:' | awk '{print $2}') $(echo $($FALCO --version | grep 'Schema version:' | awk '{print $3}') $($FALCO --list --markdown | grep '^`' | sort) $($FALCO --list-events | sort) | sha256sum) // It represents the fields supported by this version of Falco, // the event types, and the underlying driverevent schema. It's used to // detetect changes in engine version in our CI jobs. -#define FALCO_ENGINE_CHECKSUM "41b5dc700216b243d294b40c46264d4e89d0ee00098fdc1c21bb4b1e7639da06" +#define FALCO_ENGINE_CHECKSUM "98c6e665031b95c666a9ab02d5470e7008e8636bf02f4cc410912005b90dff5c" diff --git a/userspace/falco/app/actions/print_syscall_events.cpp b/userspace/falco/app/actions/print_syscall_events.cpp index 681fa5808d9..e3ef70e55bc 100644 --- a/userspace/falco/app/actions/print_syscall_events.cpp +++ b/userspace/falco/app/actions/print_syscall_events.cpp @@ -16,6 +16,8 @@ limitations under the License. #include "actions.h" #include "helpers.h" +#include "../app.h" +#include "../../versions_info.h" using namespace falco::app; using namespace falco::app::actions; @@ -28,10 +30,56 @@ struct event_entry const ppm_event_info* info; }; -static std::vector get_event_entries(bool include_generics, const libsinsp::events::set& available) +struct events_by_category { - event_entry entry; - std::vector events; + std::vector syscalls; + std::vector tracepoints; + std::vector pluginevents; + std::vector metaevents; + + void add_event(ppm_event_code e, bool available, std::string name = "") { + event_entry entry; + + entry.is_enter = PPME_IS_ENTER(e); + entry.info = libsinsp::events::info(e); + entry.available = available; + + if (name == "") + { + entry.name = entry.info->name; + } else { + entry.name = name; + } + + if (libsinsp::events::is_syscall_event(e)) + { + syscalls.push_back(entry); + return; + } + + if (libsinsp::events::is_tracepoint_event(e)) + { + tracepoints.push_back(entry); + return; + } + + if (libsinsp::events::is_plugin_event(e)) + { + pluginevents.push_back(entry); + return; + } + + if (libsinsp::events::is_metaevent(e)) + { + metaevents.push_back(entry); + return; + } + } +}; + +static struct events_by_category get_event_entries_by_category(bool include_generics, const libsinsp::events::set& available) +{ + events_by_category result; // skip generic events for (const auto& e: libsinsp::events::all_event_set()) @@ -41,11 +89,7 @@ static std::vector get_event_entries(bool include_generics, const l && !libsinsp::events::is_unused_event(e) && !libsinsp::events::is_unknown_event(e)) { - entry.is_enter = PPME_IS_ENTER(e); - entry.available = available.contains(e); - entry.info = libsinsp::events::info(e); - entry.name = entry.info->name; - events.push_back(entry); + result.add_event(e, available.contains(e)); } } @@ -55,60 +99,104 @@ static std::vector get_event_entries(bool include_generics, const l const auto names = libsinsp::events::event_set_to_names({ppm_event_code::PPME_GENERIC_E}); for (const auto& name : names) { - entry.is_enter = PPME_IS_ENTER(ppm_event_code::PPME_GENERIC_E); - entry.available = available.contains(ppm_event_code::PPME_GENERIC_E); - entry.info = libsinsp::events::info(ppm_event_code::PPME_GENERIC_E); - entry.name = name; - events.push_back(entry); - - entry.is_enter = PPME_IS_ENTER(ppm_event_code::PPME_GENERIC_X); - entry.available = available.contains(ppm_event_code::PPME_GENERIC_X); - entry.info = libsinsp::events::info(ppm_event_code::PPME_GENERIC_X); - entry.name = name; - events.push_back(entry); + result.add_event(ppm_event_code::PPME_GENERIC_E, available.contains(ppm_event_code::PPME_GENERIC_E), name); + result.add_event(ppm_event_code::PPME_GENERIC_X, available.contains(ppm_event_code::PPME_GENERIC_X), name); } } - return events; + return result; } -falco::app::run_result falco::app::actions::print_syscall_events(falco::app::state& s) +static bool is_flag_type(ppm_param_type type) { - if(s.options.list_syscall_events) + return (type == PT_FLAGS8 || type == PT_FLAGS16 || type == PT_FLAGS32 || + type == PT_ENUMFLAGS8 || type == PT_ENUMFLAGS16 || type == PT_ENUMFLAGS32); +} + +static void print_param(const struct ppm_param_info *param, bool markdown) { + printf("%s **%s**", param_type_to_string(param->type), param->name); + + if (is_flag_type(param->type) && param->info) { + auto flag_info = static_cast(param->info); + + printf(": "); + for (size_t i = 0; flag_info[i].name != NULL; i++) { + if (i != 0) + { + printf(", "); + } + + if (markdown) { + printf("*%s*", flag_info[i].name); + } else { + printf("%s", flag_info[i].name); + } + } + } +} + +static void print_events(const std::vector &events, bool markdown) +{ + if(markdown) { - const auto events = get_event_entries(true, libsinsp::events::all_event_set()); + printf("Default | Dir | Name | Params \n"); + printf(":-------|:----|:-----|:-----\n"); + } - if(s.options.markdown) + for (const auto& e : events) + { + char dir = e.is_enter ? '>' : '<'; + if (markdown) + { + printf(e.available ? "Yes" : "No"); + printf(" | `%c` | `%s` | ", dir, e.name.c_str()); + } + else { - printf("Falco | Dir | Event\n"); - printf(":-----|:----|:-----\n"); + printf("%c %s(", dir, e.name.c_str()); } - for (const auto& e : events) + for(uint32_t k = 0; k < e.info->nparams; k++) { - char dir = e.is_enter ? '>' : '<'; - if (s.options.markdown) - { - printf(e.available ? "Yes" : "No"); - printf(" | %c | **%s**(", dir, e.name.c_str()); - } - else + if(k != 0) { - printf("%c %s(", dir, e.name.c_str()); + printf(", "); } - for(uint32_t k = 0; k < e.info->nparams; k++) - { - if(k != 0) - { - printf(", "); - } - - printf("%s %s", param_type_to_string(e.info->params[k].type), - e.info->params[k].name); - } + print_param(&e.info->params[k], markdown); + } + if (markdown) + { + printf("\n"); + } + else + { printf(")\n"); } + } +} + +falco::app::run_result falco::app::actions::print_syscall_events(falco::app::state& s) +{ + if(s.options.list_syscall_events) + { + const falco::versions_info info(s.offline_inspector); + printf("The events below are valid for Falco *Schema Version*: %s\n", info.driver_schema_version.c_str()); + + const libsinsp::events::set available = libsinsp::events::all_event_set().diff(sc_set_to_event_set(falco::app::ignored_sc_set())); + const struct events_by_category events_bc = get_event_entries_by_category(true, available); + + printf("## Syscall events\n\n"); + print_events(events_bc.syscalls, s.options.markdown); + + printf("\n\n## Tracepoint events\n\n"); + print_events(events_bc.tracepoints, s.options.markdown); + + printf("\n\n## Plugin events\n\n"); + print_events(events_bc.pluginevents, s.options.markdown); + + printf("\n\n## Metaevents\n\n"); + print_events(events_bc.metaevents, s.options.markdown); return run_result::exit(); } diff --git a/userspace/falco/app/options.cpp b/userspace/falco/app/options.cpp index f76a60fa706..63818046be2 100644 --- a/userspace/falco/app/options.cpp +++ b/userspace/falco/app/options.cpp @@ -203,10 +203,10 @@ void options::define(cxxopts::Options& opts) ("L", "Show the name and description of all rules and exit. If json_output is set to true, it prints details about all rules, macros, and lists in JSON format.", cxxopts::value(describe_all_rules)->default_value("false")) ("l", "Show the name and description of the rule specified and exit. If json_output is set to true, it prints details about the rule in JSON format.", cxxopts::value(describe_rule), "") ("list", "List all defined fields and exit. If is provided, only list those fields for the source . Current values for are \"syscall\" or any source from a configured plugin with event sourcing capability.", cxxopts::value(list_source_fields)->implicit_value(""), "") - ("list-syscall-events", "List all defined 'syscall' events and exit.", cxxopts::value(list_syscall_events)) + ("list-events", "List all defined syscall events, metaevents, tracepoint events and exit.", cxxopts::value(list_syscall_events)) ("list-plugins", "Print info on all loaded plugins and exit.", cxxopts::value(list_plugins)->default_value("false")) ("M", "Stop Falco execution after are passed.", cxxopts::value(duration_to_tot)->default_value("0"), "") - ("markdown", "Print output in Markdown format when used in conjunction with --list or --list-syscall-events options. It has no effect when used with other options.", cxxopts::value(markdown)) + ("markdown", "Print output in Markdown format when used in conjunction with --list or --list-events options. It has no effect when used with other options.", cxxopts::value(markdown)) ("N", "Only print field names when used in conjunction with the --list option. It has no effect when used with other options.", cxxopts::value(names_only)->default_value("false")) ("nodriver", "Do not use a driver to instrument the kernel. If a loaded plugin has event-sourcing capability and can produce system events, it will be used for event collection. Otherwise, no event will be collected.", cxxopts::value(nodriver)->default_value("false")) ("o,option", "Set the value of option to . Overrides values in the configuration file. can be identified using its location in the configuration file using dot notation. Elements of list entries can be accessed via square brackets [].\n E.g. base.id = val\n base.subvalue.subvalue2 = val\n base.list[1]=val", cxxopts::value(cmdline_config_options), "=")