diff --git a/unit_tests/engine/test_filter_evttype_resolver.cpp b/unit_tests/engine/test_filter_evttype_resolver.cpp index 30d7e7c2..dce6ab38 100644 --- a/unit_tests/engine/test_filter_evttype_resolver.cpp +++ b/unit_tests/engine/test_filter_evttype_resolver.cpp @@ -19,6 +19,8 @@ limitations under the License. #include #include +#define ASSERT_FILTER_EQ(a, b) { ASSERT_EQ(get_filter_set(a), get_filter_set(b)); } + std::set get_filter_set(const string &fltstr) { set actual; @@ -72,7 +74,7 @@ TEST(EvtTypeResolver, check_openat) ASSERT_EQ(get_filter_set("evt.type!=openat"), not_openat); ASSERT_EQ(get_filter_set("not not not evt.type = openat"), not_openat); ASSERT_EQ(get_filter_set("not evt.type=openat"), not_openat); - ASSERT_EQ(get_filter_set("evt.type=close or not (evt.type=openat and proc.name=nginx)"), not_openat); + ASSERT_EQ(get_filter_set("evt.type=close or evt.type!=openat"), not_openat); } TEST(EvtTypeResolver, check_openat_or_close) @@ -106,6 +108,8 @@ TEST(EvtTypeResolver, check_all_events) ASSERT_EQ(get_filter_set("evt.type=openat or proc.name=nginx"), all_events); ASSERT_EQ(get_filter_set("evt.type=openat or (proc.name=nginx)"), all_events); ASSERT_EQ(get_filter_set("(evt.type=openat) or proc.name=nginx"), all_events); + ASSERT_EQ(get_filter_set("evt.type=close or not (evt.type=openat and proc.name=nginx)"), all_events); + ASSERT_EQ(get_filter_set("evt.type=openat or not (evt.type=close and proc.name=nginx)"), all_events); } TEST(EvtTypeResolver, check_no_events) @@ -116,3 +120,112 @@ TEST(EvtTypeResolver, check_no_events) ASSERT_EQ(get_filter_set("evt.type=openat and (evt.type=close and proc.name=nginx)"), no_events); ASSERT_EQ(get_filter_set("evt.type=openat and (evt.type=close)"), no_events); } + +TEST(EvtTypeResolver, check_properties) +{ + std::set no_events = {}; + + // see: https://github.com/falcosecurity/libs/pull/854#issuecomment-1411151732 + ASSERT_FILTER_EQ( + "evt.type in (connect, execve, accept, mmap, container) and not (proc.name=cat and evt.type=mmap)", + "evt.type in (accept, connect, container, execve, mmap)"); + ASSERT_EQ(get_filter_set("(evt.type=mmap and not evt.type=mmap)"), no_events); + + // defining algebraic base sets + std::string zerof = "(evt.type in ())"; ///< "zero"-set: no evt type should matches the filter + std::string onef = "(evt.type exists)"; ///< "one"-set: all evt types should match the filter + std::string neutral1 = "(proc.name=cat)"; ///< "neutral"-sets: evt types are not checked in the filter + std::string neutral2 = "(not proc.name=cat)"; + ASSERT_FILTER_EQ(onef, neutral1); + ASSERT_FILTER_EQ(onef, neutral2); + + // algebraic set properties + // 1' = 0 + ASSERT_FILTER_EQ("not " + onef, zerof); + // 0' = 1 + ASSERT_FILTER_EQ("not " + zerof, onef); + // (A')' = A + ASSERT_FILTER_EQ("evt.type=mmap", "not (not evt.type=mmap)"); + // A * A' = 0 + ASSERT_EQ(get_filter_set(zerof), no_events); + // A + A' = 1 + ASSERT_FILTER_EQ("evt.type=mmap or not evt.type=mmap", onef); + ASSERT_FILTER_EQ("evt.type=mmap or not evt.type=mmap", neutral1); + ASSERT_FILTER_EQ("evt.type=mmap or not evt.type=mmap", neutral2); + // 0 * 1 = 0 + ASSERT_FILTER_EQ(zerof + " and " + onef, zerof); + ASSERT_FILTER_EQ(zerof + " and " + neutral1, zerof); + ASSERT_FILTER_EQ(zerof + " and " + neutral2, zerof); + // 0 + 1 = 1 + ASSERT_FILTER_EQ(zerof + " or " + onef, onef); + ASSERT_FILTER_EQ(zerof + " or " + neutral1, onef); + ASSERT_FILTER_EQ(zerof + " or " + neutral2, onef); + // A * 0 = 0 + ASSERT_FILTER_EQ("evt.type=mmap and " + zerof, zerof); + // A * 1 = A + ASSERT_FILTER_EQ("evt.type=mmap and " + onef, "evt.type=mmap"); + ASSERT_FILTER_EQ("evt.type=mmap and " + neutral1, "evt.type=mmap"); + ASSERT_FILTER_EQ("evt.type=mmap and " + neutral2, "evt.type=mmap"); + // A + 0 = A + ASSERT_FILTER_EQ("evt.type=mmap or " + zerof, "evt.type=mmap"); + // A + 1 = 1 + ASSERT_FILTER_EQ("evt.type=mmap or " + onef, onef); + ASSERT_FILTER_EQ("evt.type=mmap or " + neutral1, onef); + ASSERT_FILTER_EQ("evt.type=mmap or " + neutral2, onef); + // A + A = A + ASSERT_FILTER_EQ("evt.type=mmap or evt.type=mmap", "evt.type=mmap"); + // A * A = A + ASSERT_FILTER_EQ("evt.type=mmap and evt.type=mmap", "evt.type=mmap"); + + // de morgan's laws + ASSERT_FILTER_EQ( + "not (proc.name=cat or evt.type=mmap)", + "not proc.name=cat and not evt.type=mmap"); + ASSERT_FILTER_EQ( + "not (proc.name=cat or fd.type=file)", + "not proc.name=cat and not fd.type=file"); + ASSERT_FILTER_EQ( + "not (evt.type=execve or evt.type=mmap)", + "not evt.type=execve and not evt.type=mmap"); + ASSERT_FILTER_EQ( + "not (evt.type=mmap or evt.type=mmap)", + "not evt.type=mmap and not evt.type=mmap"); + ASSERT_FILTER_EQ( + "not (proc.name=cat and evt.type=mmap)", + "not proc.name=cat or not evt.type=mmap"); + ASSERT_FILTER_EQ( + "not (proc.name=cat and fd.type=file)", + "not proc.name=cat or not fd.type=file"); + ASSERT_FILTER_EQ( + "not (evt.type=execve and evt.type=mmap)", + "not evt.type=execve or not evt.type=mmap"); + ASSERT_FILTER_EQ( + "not (evt.type=mmap and evt.type=mmap)", + "not evt.type=mmap or not evt.type=mmap"); + + // negation isomorphism + ASSERT_FILTER_EQ("not evt.type=mmap", "evt.type!=mmap"); + ASSERT_FILTER_EQ("not proc.name=cat", "proc.name!=cat"); + + // commutative property (and) + ASSERT_FILTER_EQ("evt.type=execve and evt.type=mmap", "evt.type=mmap and evt.type=execve"); + ASSERT_FILTER_EQ("not (evt.type=execve and evt.type=mmap)", "not (evt.type=mmap and evt.type=execve)"); + ASSERT_FILTER_EQ("not evt.type=execve and not evt.type=mmap", "not evt.type=mmap and not evt.type=execve"); + ASSERT_FILTER_EQ("proc.name=cat and evt.type=mmap", "evt.type=mmap and proc.name=cat"); + ASSERT_FILTER_EQ("not (proc.name=cat and evt.type=mmap)", "not (evt.type=mmap and proc.name=cat)"); + ASSERT_FILTER_EQ("not proc.name=cat and not evt.type=mmap", "not evt.type=mmap and not proc.name=cat"); + ASSERT_FILTER_EQ("proc.name=cat and fd.type=file", "fd.type=file and proc.name=cat"); + ASSERT_FILTER_EQ("not (proc.name=cat and fd.type=file)", "not (fd.type=file and proc.name=cat)"); + ASSERT_FILTER_EQ("not proc.name=cat and not fd.type=file", "not fd.type=file and not proc.name=cat"); + + // commutative property (or) + ASSERT_FILTER_EQ("evt.type=execve or evt.type=mmap", "evt.type=mmap or evt.type=execve"); + ASSERT_FILTER_EQ("not (evt.type=execve or evt.type=mmap)", "not (evt.type=mmap or evt.type=execve)"); + ASSERT_FILTER_EQ("not evt.type=execve or not evt.type=mmap", "not evt.type=mmap or not evt.type=execve"); + ASSERT_FILTER_EQ("proc.name=cat or evt.type=mmap", "evt.type=mmap or proc.name=cat"); + ASSERT_FILTER_EQ("not (proc.name=cat or evt.type=mmap)", "not (evt.type=mmap or proc.name=cat)"); + ASSERT_FILTER_EQ("not proc.name=cat or not evt.type=mmap", "not evt.type=mmap or not proc.name=cat"); + ASSERT_FILTER_EQ("proc.name=cat or fd.type=file", "fd.type=file or proc.name=cat"); + ASSERT_FILTER_EQ("not (proc.name=cat or fd.type=file)", "not (fd.type=file or proc.name=cat)"); + ASSERT_FILTER_EQ("not proc.name=cat or not fd.type=file", "not fd.type=file or not proc.name=cat"); +}