diff --git a/unit_tests/falco/app/actions/test_configure_interesting_sets.cpp b/unit_tests/falco/app/actions/test_configure_interesting_sets.cpp index 8688de11..6da89917 100644 --- a/unit_tests/falco/app/actions/test_configure_interesting_sets.cpp +++ b/unit_tests/falco/app/actions/test_configure_interesting_sets.cpp @@ -91,6 +91,7 @@ static std::shared_ptr mock_engine_from_filters(const strset_t& fi TEST(ConfigureInterestingSets, engine_codes_syscalls_set) { + auto engine = mock_engine_from_filters(s_sample_filters); auto enabled_count = engine->num_rules_for_ruleset(s_sample_ruleset); ASSERT_EQ(enabled_count, s_sample_filters.size()); @@ -112,32 +113,32 @@ TEST(ConfigureInterestingSets, engine_codes_syscalls_set) TEST(ConfigureInterestingSets, preconditions_postconditions) { - falco::app::state s; auto mock_engine = mock_engine_from_filters(s_sample_filters); + falco::app::state s1; - s.engine = mock_engine; - s.config = nullptr; - auto result = falco::app::actions::configure_interesting_sets(s); + s1.engine = mock_engine; + s1.config = nullptr; + auto result = falco::app::actions::configure_interesting_sets(s1); ASSERT_FALSE(result.success); ASSERT_NE(result.errstr, ""); - s.engine = nullptr; - s.config = std::make_shared(); - result = falco::app::actions::configure_interesting_sets(s); + s1.engine = nullptr; + s1.config = std::make_shared(); + result = falco::app::actions::configure_interesting_sets(s1); ASSERT_FALSE(result.success); ASSERT_NE(result.errstr, ""); - s.engine = mock_engine; - s.config = std::make_shared(); - result = falco::app::actions::configure_interesting_sets(s); + s1.engine = mock_engine; + s1.config = std::make_shared(); + result = falco::app::actions::configure_interesting_sets(s1); ASSERT_TRUE(result.success); ASSERT_EQ(result.errstr, ""); - auto prev_selection_size = s.selected_sc_set.size(); - result = falco::app::actions::configure_interesting_sets(s); + auto prev_selection_size = s1.selected_sc_set.size(); + result = falco::app::actions::configure_interesting_sets(s1); ASSERT_TRUE(result.success); ASSERT_EQ(result.errstr, ""); - ASSERT_EQ(prev_selection_size, s.selected_sc_set.size()); + ASSERT_EQ(prev_selection_size, s1.selected_sc_set.size()); } TEST(ConfigureInterestingSets, engine_codes_nonsyscalls_set) @@ -173,11 +174,13 @@ TEST(ConfigureInterestingSets, engine_codes_nonsyscalls_set) TEST(ConfigureInterestingSets, selection_not_allevents) { + falco::app::state s2; // run app action with fake engine and without the `-A` option - falco::app::state s; - s.engine = mock_engine_from_filters(s_sample_filters); - s.options.all_events = false; - auto result = falco::app::actions::configure_interesting_sets(s); + s2.engine = mock_engine_from_filters(s_sample_filters); + s2.options.all_events = false; + + ASSERT_EQ(s2.options.all_events, false); + auto result = falco::app::actions::configure_interesting_sets(s2); ASSERT_TRUE(result.success); ASSERT_EQ(result.errstr, ""); @@ -185,8 +188,8 @@ TEST(ConfigureInterestingSets, selection_not_allevents) // also check if a warning has been printed in stderr // check that the final selected set is the one expected - ASSERT_GT(s.selected_sc_set.size(), 1); - auto selected_sc_names = libsinsp::events::sc_set_to_names(s.selected_sc_set); + ASSERT_GT(s2.selected_sc_set.size(), 1); + auto selected_sc_names = libsinsp::events::sc_set_to_names(s2.selected_sc_set); auto expected_sc_names = strset_t({ // note: we expect the "read" syscall to have been erased "connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", // from ruleset @@ -201,7 +204,7 @@ TEST(ConfigureInterestingSets, selection_not_allevents) ASSERT_NAMES_NOCONTAIN(selected_sc_names, erased_sc_names); // check that final selected set is exactly sinsp state + ruleset - auto rule_set = s.engine->sc_codes_for_ruleset(s_sample_source, s_sample_ruleset); + auto rule_set = s2.engine->sc_codes_for_ruleset(s_sample_source, s_sample_ruleset); auto state_set = libsinsp::events::sinsp_state_sc_set(); for (const auto &erased : io_set) { @@ -210,17 +213,17 @@ TEST(ConfigureInterestingSets, selection_not_allevents) } auto union_set = state_set.merge(rule_set); auto inter_set = state_set.intersect(rule_set); - ASSERT_EQ(s.selected_sc_set.size(), state_set.size() + rule_set.size() - inter_set.size()); - ASSERT_EQ(s.selected_sc_set, union_set); + ASSERT_EQ(s2.selected_sc_set.size(), state_set.size() + rule_set.size() - inter_set.size()); + ASSERT_EQ(s2.selected_sc_set, union_set); } TEST(ConfigureInterestingSets, selection_allevents) { + falco::app::state s3; // run app action with fake engine and with the `-A` option - falco::app::state s; - s.engine = mock_engine_from_filters(s_sample_filters); - s.options.all_events = true; - auto result = falco::app::actions::configure_interesting_sets(s); + s3.engine = mock_engine_from_filters(s_sample_filters); + s3.options.all_events = true; + auto result = falco::app::actions::configure_interesting_sets(s3); ASSERT_TRUE(result.success); ASSERT_EQ(result.errstr, ""); @@ -228,8 +231,8 @@ TEST(ConfigureInterestingSets, selection_allevents) // also check if a warning has not been printed in stderr // check that the final selected set is the one expected - ASSERT_GT(s.selected_sc_set.size(), 1); - auto selected_sc_names = libsinsp::events::sc_set_to_names(s.selected_sc_set); + ASSERT_GT(s3.selected_sc_set.size(), 1); + auto selected_sc_names = libsinsp::events::sc_set_to_names(s3.selected_sc_set); auto expected_sc_names = strset_t({ // note: we expect the "read" syscall to not be erased "connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", "read", // from ruleset @@ -239,29 +242,29 @@ TEST(ConfigureInterestingSets, selection_allevents) ASSERT_NAMES_CONTAIN(selected_sc_names, expected_sc_names); // check that final selected set is exactly sinsp state + ruleset - auto rule_set = s.engine->sc_codes_for_ruleset(s_sample_source, s_sample_ruleset); + auto rule_set = s3.engine->sc_codes_for_ruleset(s_sample_source, s_sample_ruleset); auto state_set = libsinsp::events::sinsp_state_sc_set(); auto union_set = state_set.merge(rule_set); auto inter_set = state_set.intersect(rule_set); - ASSERT_EQ(s.selected_sc_set.size(), state_set.size() + rule_set.size() - inter_set.size()); - ASSERT_EQ(s.selected_sc_set, union_set); + ASSERT_EQ(s3.selected_sc_set.size(), state_set.size() + rule_set.size() - inter_set.size()); + ASSERT_EQ(s3.selected_sc_set, union_set); } TEST(ConfigureInterestingSets, selection_generic_evts) { + falco::app::state s4; // run app action with fake engine and without the `-A` option - falco::app::state s; - s.options.all_events = false; + s4.options.all_events = false; auto filters = s_sample_filters; filters.insert(s_sample_generic_filters.begin(), s_sample_generic_filters.end()); - s.engine = mock_engine_from_filters(filters); - auto result = falco::app::actions::configure_interesting_sets(s); + s4.engine = mock_engine_from_filters(filters); + auto result = falco::app::actions::configure_interesting_sets(s4); ASSERT_TRUE(result.success); ASSERT_EQ(result.errstr, ""); // check that the final selected set is the one expected - ASSERT_GT(s.selected_sc_set.size(), 1); - auto selected_sc_names = libsinsp::events::sc_set_to_names(s.selected_sc_set); + ASSERT_GT(s4.selected_sc_set.size(), 1); + auto selected_sc_names = libsinsp::events::sc_set_to_names(s4.selected_sc_set); auto expected_sc_names = strset_t({ // note: we expect the "read" syscall to not be erased "connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", // from ruleset @@ -281,19 +284,19 @@ TEST(ConfigureInterestingSets, selection_generic_evts) // - if `-A` is not set, events from the IO set are removed from the selected set TEST(ConfigureInterestingSets, selection_custom_base_set) { + falco::app::state s5; // run app action with fake engine and without the `-A` option - falco::app::state s; - s.options.all_events = true; - s.engine = mock_engine_from_filters(s_sample_filters); + s5.options.all_events = true; + s5.engine = mock_engine_from_filters(s_sample_filters); auto default_base_set = libsinsp::events::sinsp_state_sc_set(); // non-empty custom base set (both positive and negative) - s.config->m_base_syscalls_repair = false; - s.config->m_base_syscalls_custom_set = {"syncfs", "!accept"}; - auto result = falco::app::actions::configure_interesting_sets(s); + s5.config->m_base_syscalls_repair = false; + s5.config->m_base_syscalls_custom_set = {"syncfs", "!accept"}; + auto result = falco::app::actions::configure_interesting_sets(s5); ASSERT_TRUE(result.success); ASSERT_EQ(result.errstr, ""); - auto selected_sc_names = libsinsp::events::sc_set_to_names(s.selected_sc_set); + auto selected_sc_names = libsinsp::events::sc_set_to_names(s5.selected_sc_set); auto expected_sc_names = strset_t({ // note: `syncfs` has been added due to the custom base set, and `accept` // has been remove due to the negative base set. @@ -307,22 +310,22 @@ TEST(ConfigureInterestingSets, selection_custom_base_set) ASSERT_NAMES_EQ(selected_sc_names, expected_sc_names); // non-empty custom base set (both positive and negative with collision) - s.config->m_base_syscalls_repair = false; - s.config->m_base_syscalls_custom_set = {"syncfs", "accept", "!accept"}; - result = falco::app::actions::configure_interesting_sets(s); + s5.config->m_base_syscalls_repair = false; + s5.config->m_base_syscalls_custom_set = {"syncfs", "accept", "!accept"}; + result = falco::app::actions::configure_interesting_sets(s5); ASSERT_TRUE(result.success); ASSERT_EQ(result.errstr, ""); - selected_sc_names = libsinsp::events::sc_set_to_names(s.selected_sc_set); + selected_sc_names = libsinsp::events::sc_set_to_names(s5.selected_sc_set); // note: in case of collision, negation has priority, so the expected // names are the same as the case above ASSERT_NAMES_EQ(selected_sc_names, expected_sc_names); // non-empty custom base set (only positive) - s.config->m_base_syscalls_custom_set = {"syncfs"}; - result = falco::app::actions::configure_interesting_sets(s); + s5.config->m_base_syscalls_custom_set = {"syncfs"}; + result = falco::app::actions::configure_interesting_sets(s5); ASSERT_TRUE(result.success); ASSERT_EQ(result.errstr, ""); - selected_sc_names = libsinsp::events::sc_set_to_names(s.selected_sc_set); + selected_sc_names = libsinsp::events::sc_set_to_names(s5.selected_sc_set); expected_sc_names = strset_t({ // note: accept is not negated anymore "connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", "read", "syncfs", "sched_process_exit" @@ -330,11 +333,11 @@ TEST(ConfigureInterestingSets, selection_custom_base_set) ASSERT_NAMES_EQ(selected_sc_names, expected_sc_names); // non-empty custom base set (only negative) - s.config->m_base_syscalls_custom_set = {"!accept"}; - result = falco::app::actions::configure_interesting_sets(s); + s5.config->m_base_syscalls_custom_set = {"!accept"}; + result = falco::app::actions::configure_interesting_sets(s5); ASSERT_TRUE(result.success); ASSERT_EQ(result.errstr, ""); - selected_sc_names = libsinsp::events::sc_set_to_names(s.selected_sc_set); + selected_sc_names = libsinsp::events::sc_set_to_names(s5.selected_sc_set); expected_sc_names = unordered_set_union( libsinsp::events::sc_set_to_names(default_base_set), strset_t({ "connect", "umount2", "open", "ptrace", "mmap", "execve", "read"})); @@ -344,12 +347,12 @@ TEST(ConfigureInterestingSets, selection_custom_base_set) ASSERT_NAMES_EQ(selected_sc_names, expected_sc_names); // non-empty custom base set (positive, without -A) - s.options.all_events = false; - s.config->m_base_syscalls_custom_set = {"read"}; - result = falco::app::actions::configure_interesting_sets(s); + s5.options.all_events = false; + s5.config->m_base_syscalls_custom_set = {"read"}; + result = falco::app::actions::configure_interesting_sets(s5); ASSERT_TRUE(result.success); ASSERT_EQ(result.errstr, ""); - selected_sc_names = libsinsp::events::sc_set_to_names(s.selected_sc_set); + selected_sc_names = libsinsp::events::sc_set_to_names(s5.selected_sc_set); expected_sc_names = strset_t({ // note: read is both part of the custom base set and the rules set, // but we expect the unset -A option to take precedence @@ -362,23 +365,22 @@ TEST(ConfigureInterestingSets, selection_custom_base_set) TEST(ConfigureInterestingSets, selection_custom_base_set_repair) { + falco::app::state s6; // run app action with fake engine and without the `-A` option - falco::app::state s; - s.options.all_events = false; - s.engine = mock_engine_from_filters(s_sample_filters); + s6.options.all_events = false; + s6.engine = mock_engine_from_filters(s_sample_filters); - // simulate empty custom set but repair option set. // note: here we use file syscalls (e.g. open, openat) and have a custom // positive set, so we expect syscalls such as "close" to be selected as // repaired. Also, given that we use some network syscalls, we expect "bind" // to be selected event if we negate it, because repairment should have // take precedence. - s.config->m_base_syscalls_custom_set = {"openat", "!bind"}; - s.config->m_base_syscalls_repair = true; - auto result = falco::app::actions::configure_interesting_sets(s); + s6.config->m_base_syscalls_custom_set = {"openat", "!bind"}; + s6.config->m_base_syscalls_repair = true; + auto result = falco::app::actions::configure_interesting_sets(s6); ASSERT_TRUE(result.success); ASSERT_EQ(result.errstr, ""); - auto selected_sc_names = libsinsp::events::sc_set_to_names(s.selected_sc_set); + auto selected_sc_names = libsinsp::events::sc_set_to_names(s6.selected_sc_set); auto expected_sc_names = strset_t({ // note: expecting syscalls from mock rules and `sinsp_repair_state_sc_set` enforced syscalls "connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", "sched_process_exit", \ @@ -388,3 +390,29 @@ TEST(ConfigureInterestingSets, selection_custom_base_set_repair) auto unexpected_sc_names = libsinsp::events::sc_set_to_names(libsinsp::events::io_sc_set()); ASSERT_NAMES_NOCONTAIN(selected_sc_names, unexpected_sc_names); } + +TEST(ConfigureInterestingSets, selection_empty_custom_base_set_repair) +{ + falco::app::state s7; + // run app action with fake engine and with the `-A` option + s7.options.all_events = true; + s7.engine = mock_engine_from_filters(s_sample_filters); + + // simulate empty custom set but repair option set. + s7.config->m_base_syscalls_custom_set = {}; + s7.config->m_base_syscalls_repair = true; + auto result = falco::app::actions::configure_interesting_sets(s7); + auto s7_rules_set = s7.engine->sc_codes_for_ruleset(s_sample_source, s_sample_ruleset); + ASSERT_TRUE(result.success); + ASSERT_EQ(result.errstr, ""); + auto selected_sc_names = libsinsp::events::sc_set_to_names(s7.selected_sc_set); + auto expected_sc_names = strset_t({ + // note: expecting syscalls from mock rules and `sinsp_repair_state_sc_set` enforced syscalls + "connect", "accept", "accept4", "umount2", "open", "ptrace", "mmap", "execve", "sched_process_exit", \ + "bind", "socket", "clone3", "close", "setuid" + }); + ASSERT_NAMES_CONTAIN(selected_sc_names, expected_sc_names); + auto s7_state_set = libsinsp::events::sinsp_repair_state_sc_set(s7_rules_set); + ASSERT_EQ(s7.selected_sc_set, s7_state_set); + ASSERT_EQ(s7.selected_sc_set.size(), s7_state_set.size()); +}