diff --git a/userspace/engine/falco_engine.cpp b/userspace/engine/falco_engine.cpp index 952c8a37..023d2bde 100644 --- a/userspace/engine/falco_engine.cpp +++ b/userspace/engine/falco_engine.cpp @@ -302,31 +302,9 @@ unique_ptr falco_engine::process_sinsp_event(sinsp_ev } unique_ptr res(new rule_result()); + res->source = "syscall"; - std::lock_guard guard(m_ls_semaphore); - lua_getglobal(m_ls, lua_on_event.c_str()); - if(lua_isfunction(m_ls, -1)) - { - lua_pushnumber(m_ls, ev->get_check_id()); - - if(lua_pcall(m_ls, 1, 3, 0) != 0) - { - const char* lerr = lua_tostring(m_ls, -1); - string err = "Error invoking function output: " + string(lerr); - throw falco_exception(err); - } - res->evt = ev; - const char *p = lua_tostring(m_ls, -3); - res->rule = p; - res->source = "syscall"; - res->priority_num = (falco_common::priority_type) lua_tonumber(m_ls, -2); - res->format = lua_tostring(m_ls, -1); - lua_pop(m_ls, 3); - } - else - { - throw falco_exception("No function " + lua_on_event + " found in lua compiler module"); - } + populate_rule_result(res, ev); return res; } @@ -350,33 +328,50 @@ unique_ptr falco_engine::process_k8s_audit_event(json } unique_ptr res(new rule_result()); + res->source = "k8s_audit"; + populate_rule_result(res, ev); + + return res; +} + +void falco_engine::populate_rule_result(unique_ptr &res, gen_event *ev) +{ std::lock_guard guard(m_ls_semaphore); lua_getglobal(m_ls, lua_on_event.c_str()); if(lua_isfunction(m_ls, -1)) { lua_pushnumber(m_ls, ev->get_check_id()); - if(lua_pcall(m_ls, 1, 3, 0) != 0) + if(lua_pcall(m_ls, 1, 4, 0) != 0) { const char* lerr = lua_tostring(m_ls, -1); string err = "Error invoking function output: " + string(lerr); throw falco_exception(err); } - res->evt = ev; - const char *p = lua_tostring(m_ls, -3); + const char *p = lua_tostring(m_ls, -4); res->rule = p; - res->source = "k8s_audit"; - res->priority_num = (falco_common::priority_type) lua_tonumber(m_ls, -2); - res->format = lua_tostring(m_ls, -1); - lua_pop(m_ls, 3); + res->evt = ev; + res->priority_num = (falco_common::priority_type) lua_tonumber(m_ls, -3); + res->format = lua_tostring(m_ls, -2); + + // Exception fields are passed back as a table + lua_pushnil(m_ls); /* first key */ + while (lua_next(m_ls, -2) != 0) { + // key is at index -2, value is at index + // -1. We want the keys. + res->exception_fields.insert(luaL_checkstring(m_ls, -2)); + + // Remove value, keep key for next iteration + lua_pop(m_ls, 1); + } + + lua_pop(m_ls, 4); } else { throw falco_exception("No function " + lua_on_event + " found in lua compiler module"); } - - return res; } bool falco_engine::parse_k8s_audit_json(nlohmann::json &j, std::list &evts, bool top) diff --git a/userspace/engine/falco_engine.h b/userspace/engine/falco_engine.h index 768eaf60..a5459a66 100644 --- a/userspace/engine/falco_engine.h +++ b/userspace/engine/falco_engine.h @@ -160,6 +160,7 @@ public: std::string source; falco_common::priority_type priority_num; std::string format; + std::set exception_fields; }; // @@ -262,6 +263,8 @@ private: std::unique_ptr m_sinsp_rules; std::unique_ptr m_k8s_audit_rules; + void populate_rule_result(unique_ptr &res, gen_event *ev); + // // Here's how the sampling ratio and multiplier influence // whether or not an event is dropped in diff --git a/userspace/engine/lua/rule_loader.lua b/userspace/engine/lua/rule_loader.lua index 212451b6..d232457f 100644 --- a/userspace/engine/lua/rule_loader.lua +++ b/userspace/engine/lua/rule_loader.lua @@ -674,7 +674,8 @@ function load_rules_doc(rules_mgr, doc, load_state) end -- cond and not ((proc.name=apk and fd.directory=/usr/lib/alpine) or (proc.name=npm and fd.directory=/usr/node/bin) or ...) -function build_exception_condition_string_multi_fields(eitem) +-- Populates exfields with all fields used +function build_exception_condition_string_multi_fields(eitem, exfields) local fields = eitem['fields'] local comps = eitem['comps'] @@ -721,6 +722,7 @@ function build_exception_condition_string_multi_fields(eitem) end icond = icond..fields[k].." "..comps[k].." "..istr + exfields[fields[k]] = true end icond=icond..")" @@ -737,7 +739,7 @@ function build_exception_condition_string_multi_fields(eitem) end -function build_exception_condition_string_single_field(eitem) +function build_exception_condition_string_single_field(eitem, exfields) local icond = "" @@ -753,6 +755,8 @@ function build_exception_condition_string_single_field(eitem) icond = icond..", " end + exfields[eitem['fields']] = true + icond = icond..quote_item(value) end @@ -896,15 +900,17 @@ function load_rules(sinsp_lua_parser, local econd = "" + local exfields = {} + -- Turn exceptions into condition strings and add them to each -- rule's condition for _, eitem in ipairs(v['exceptions']) do local icond, err if type(eitem['fields']) == "table" then - icond, err = build_exception_condition_string_multi_fields(eitem) + icond, err = build_exception_condition_string_multi_fields(eitem, exfields) else - icond, err = build_exception_condition_string_single_field(eitem) + icond, err = build_exception_condition_string_single_field(eitem, exfields) end if err ~= nil then @@ -916,6 +922,8 @@ function load_rules(sinsp_lua_parser, end end + state.rules_by_name[name]['exception_fields'] = exfields + if econd ~= "" then state.rules_by_name[name]['compile_condition'] = "("..state.rules_by_name[name]['condition']..") "..econd else @@ -1143,7 +1151,14 @@ function on_event(rule_id) -- Prefix output with '*' so formatting is permissive output = "*"..rule.output - return rule.rule, rule.priority_num, output + -- Also return all fields from all exceptions + combined_rule = state.rules_by_name[rule.rule] + + if combined_rule == nil then + error ("rule_loader.on_event(): could not find rule by name: ", rule.rule) + end + + return rule.rule, rule.priority_num, output, combined_rule.exception_fields end function print_stats()