From 047f12d0f6e965a566f2c73122334d5105ee06cb Mon Sep 17 00:00:00 2001 From: Mark Stemm Date: Thu, 27 Jun 2019 16:38:09 -0700 Subject: [PATCH] More efficient searches for defined filters Instead of iterating over the entire list of filters and doing pattern matches against each defined filter, perform table lookups. For filters that take arguments e.g. proc.aname[3] or evt.arg.xxx, split the filtercheck string on bracket/dot and check the values against a table. There are now two tables of defined filters: defined_arg_filters and defined_noarg_filters. Each filter is put into a table depending on whether the filter takes an argument or not. Signed-off-by: Mark Stemm --- userspace/engine/lua/rule_loader.lua | 30 +++++++++-- userspace/engine/rules.cpp | 74 +++++++++++++++++++--------- userspace/engine/rules.h | 3 +- 3 files changed, 78 insertions(+), 29 deletions(-) diff --git a/userspace/engine/lua/rule_loader.lua b/userspace/engine/lua/rule_loader.lua index 055dddf4..4f045b98 100644 --- a/userspace/engine/lua/rule_loader.lua +++ b/userspace/engine/lua/rule_loader.lua @@ -433,10 +433,32 @@ function load_rules(sinsp_lua_parser, for filter, _ in pairs(filters) do found = false - for pat, _ in pairs(defined_filters) do - if string.match(filter, pat) ~= nil then - found = true - break + if defined_noarg_filters[filter] ~= nil then + found = true + else + bracket_idx = string.find(filter, "[", 1, true) + + if bracket_idx ~= nil then + subfilter = string.sub(filter, 1, bracket_idx-1) + + if defined_arg_filters[subfilter] ~= nil then + found = true + end + end + + if not found then + dot_idx = string.find(filter, ".", 1, true) + + while dot_idx ~= nil do + subfilter = string.sub(filter, 1, dot_idx-1) + + if defined_arg_filters[subfilter] ~= nil then + found = true + break + end + + dot_idx = string.find(filter, ".", dot_idx+1, true) + end end end diff --git a/userspace/engine/rules.cpp b/userspace/engine/rules.cpp index c8c45ef8..140fc880 100644 --- a/userspace/engine/rules.cpp +++ b/userspace/engine/rules.cpp @@ -323,12 +323,12 @@ void falco_rules::load_rules(const string &rules_content, lua_setglobal(m_ls, m_lua_ignored_syscalls.c_str()); - // Create a table containing all filtercheck names. - lua_newtable(m_ls); - vector fc_plugins; sinsp::get_filtercheck_fields_info(&fc_plugins); + set no_argument_filters; + set argument_filters; + for(uint32_t j = 0; j < fc_plugins.size(); j++) { const filter_check_info* fci = fc_plugins[j]; @@ -350,45 +350,71 @@ void falco_rules::load_rules(const string &rules_content, // Some filters can work with or without an argument std::set flexible_filters = { - "^proc.aname", - "^proc.apid" + "proc.aname", + "proc.apid" }; - std::list fields; - std::string field_base = string("^") + fld->m_name; - if(fld->m_flags & EPF_REQUIRES_ARGUMENT || - flexible_filters.find(field_base) != flexible_filters.end()) + flexible_filters.find(fld->m_name) != flexible_filters.end()) { - fields.push_back(field_base + "[%[%.]"); + argument_filters.insert(fld->m_name); } if(!(fld->m_flags & EPF_REQUIRES_ARGUMENT) || - flexible_filters.find(field_base) != flexible_filters.end()) + flexible_filters.find(fld->m_name) != flexible_filters.end()) { - fields.push_back(field_base + "$"); - } - - for(auto &field : fields) - { - lua_pushstring(m_ls, field.c_str()); - lua_pushnumber(m_ls, 1); - lua_settable(m_ls, -3); + no_argument_filters.insert(fld->m_name); } } } for(auto &chk_field : m_engine->json_factory().get_fields()) { - for(auto &field : chk_field.fields) + for(auto &field : chk_field.m_fields) { - lua_pushstring(m_ls, field.name.c_str()); - lua_pushnumber(m_ls, 1); - lua_settable(m_ls, -3); + switch(field.m_idx_mode) + { + case json_event_filter_check::IDX_REQUIRED: + argument_filters.insert(field.m_name); + break; + case json_event_filter_check::IDX_ALLOWED: + argument_filters.insert(field.m_name); + no_argument_filters.insert(field.m_name); + break; + case json_event_filter_check::IDX_NONE: + no_argument_filters.insert(field.m_name); + break; + default: + break; + } } } - lua_setglobal(m_ls, m_lua_defined_filters.c_str()); + // Create tables containing all filtercheck + // names. They are split into names that require + // arguments and ones that do not. + + lua_newtable(m_ls); + + for(auto &field : argument_filters) + { + lua_pushstring(m_ls, field.c_str()); + lua_pushnumber(m_ls, 1); + lua_settable(m_ls, -3); + } + + lua_setglobal(m_ls, m_lua_defined_arg_filters.c_str()); + + lua_newtable(m_ls); + + for(auto &field : no_argument_filters) + { + lua_pushstring(m_ls, field.c_str()); + lua_pushnumber(m_ls, 1); + lua_settable(m_ls, -3); + } + + lua_setglobal(m_ls, m_lua_defined_noarg_filters.c_str()); lua_pushlightuserdata(m_ls, m_sinsp_lua_parser); lua_pushlightuserdata(m_ls, m_json_lua_parser); diff --git a/userspace/engine/rules.h b/userspace/engine/rules.h index 47fb454a..02037b17 100644 --- a/userspace/engine/rules.h +++ b/userspace/engine/rules.h @@ -67,7 +67,8 @@ class falco_rules string m_lua_load_rules = "load_rules"; string m_lua_ignored_syscalls = "ignored_syscalls"; string m_lua_ignored_events = "ignored_events"; - string m_lua_defined_filters = "defined_filters"; + string m_lua_defined_arg_filters = "defined_arg_filters"; + string m_lua_defined_noarg_filters = "defined_noarg_filters"; string m_lua_events = "events"; string m_lua_syscalls = "syscalls"; string m_lua_describe_rule = "describe_rule";