diff --git a/plugins/anomalydetection/src/plugin.cpp b/plugins/anomalydetection/src/plugin.cpp index 7eb03978..311d1f31 100644 --- a/plugins/anomalydetection/src/plugin.cpp +++ b/plugins/anomalydetection/src/plugin.cpp @@ -384,36 +384,36 @@ bool anomalydetection::extract_filterchecks_concat_profile(int64_t thread_id, co break; } case plugin_sinsp_filterchecks::TYPE_ANAME: + { + // todo: check implications of main thread as it's part of the libs implementation + if(field.argid < 1) { - // todo: check implications of main thread as it's part of the libs implementation - if(field.argid < 1) - { - m_comm.read_value(tr, thread_entry, tstr); - break; - } - m_ptid.read_value(tr, thread_entry, ptid); - for(uint32_t j = 0; j < field.argid; j++) + m_comm.read_value(tr, thread_entry, tstr); + break; + } + m_ptid.read_value(tr, thread_entry, ptid); + for(uint32_t j = 0; j < field.argid; j++) + { + try { - try + auto lineage = m_thread_table.get_entry(tr, ptid); + if(j == (field.argid - 1)) { - auto lineage = m_thread_table.get_entry(tr, ptid); - if(j == (field.argid - 1)) - { - m_comm.read_value(tr, lineage, tstr); - break; - } - if(ptid == 1) - { - break; - } - m_ptid.read_value(tr, lineage, ptid); + m_comm.read_value(tr, lineage, tstr); + break; } - catch(const std::exception& e) + if(ptid == 1) { + break; } + m_ptid.read_value(tr, lineage, ptid); + } + catch(const std::exception& e) + { } - break; } + break; + } case plugin_sinsp_filterchecks::TYPE_ARGS: { const char* arg = nullptr; @@ -434,6 +434,48 @@ bool anomalydetection::extract_filterchecks_concat_profile(int64_t thread_id, co }); break; } + case plugin_sinsp_filterchecks::TYPE_CMDLINE: + { + m_comm.read_value(tr, thread_entry, tstr); + const char* arg = nullptr; + auto args_table = m_thread_table.get_subtable(tr, m_args, thread_entry, st::SS_PLUGIN_ST_INT64); + args_table.iterate_entries(tr, [this, &tr, &arg, &tstr](const falcosecurity::table_entry& e) + { + arg = nullptr; + m_args_value.read_value(tr, e, arg); + if (!tstr.empty()) + { + tstr += " "; + } + if (arg) + { + tstr += arg; + } + return true; + }); + break; + } + case plugin_sinsp_filterchecks::TYPE_EXELINE: + { + m_exe.read_value(tr, thread_entry, tstr); + const char* arg = nullptr; + auto args_table = m_thread_table.get_subtable(tr, m_args, thread_entry, st::SS_PLUGIN_ST_INT64); + args_table.iterate_entries(tr, [this, &tr, &arg, &tstr](const falcosecurity::table_entry& e) + { + arg = nullptr; + m_args_value.read_value(tr, e, arg); + if (!tstr.empty()) + { + tstr += " "; + } + if (arg) + { + tstr += arg; + } + return true; + }); + break; + } case plugin_sinsp_filterchecks::TYPE_EXE: m_exe.read_value(tr, thread_entry, tstr); break; @@ -445,35 +487,35 @@ bool anomalydetection::extract_filterchecks_concat_profile(int64_t thread_id, co break; } case plugin_sinsp_filterchecks::TYPE_AEXE: + { + if(field.argid < 1) { - if(field.argid < 1) - { - m_exe.read_value(tr, thread_entry, tstr); - break; - } - m_ptid.read_value(tr, thread_entry, ptid); - for(uint32_t j = 0; j < field.argid; j++) + m_exe.read_value(tr, thread_entry, tstr); + break; + } + m_ptid.read_value(tr, thread_entry, ptid); + for(uint32_t j = 0; j < field.argid; j++) + { + try { - try + auto lineage = m_thread_table.get_entry(tr, ptid); + if(j == (field.argid - 1)) { - auto lineage = m_thread_table.get_entry(tr, ptid); - if(j == (field.argid - 1)) - { - m_exe.read_value(tr, lineage, tstr); - break; - } - if(ptid == 1) - { - break; - } - m_ptid.read_value(tr, lineage, ptid); + m_exe.read_value(tr, lineage, tstr); + break; } - catch(const std::exception& e) + if(ptid == 1) { + break; } + m_ptid.read_value(tr, lineage, ptid); + } + catch(const std::exception& e) + { } - break; } + break; + } case plugin_sinsp_filterchecks::TYPE_EXEPATH: m_exepath.read_value(tr, thread_entry, tstr); break; @@ -485,35 +527,35 @@ bool anomalydetection::extract_filterchecks_concat_profile(int64_t thread_id, co break; } case plugin_sinsp_filterchecks::TYPE_AEXEPATH: + { + if(field.argid < 1) { - if(field.argid < 1) - { - m_exepath.read_value(tr, thread_entry, tstr); - break; - } - m_ptid.read_value(tr, thread_entry, ptid); - for(uint32_t j = 0; j < field.argid; j++) + m_exepath.read_value(tr, thread_entry, tstr); + break; + } + m_ptid.read_value(tr, thread_entry, ptid); + for(uint32_t j = 0; j < field.argid; j++) + { + try { - try + auto lineage = m_thread_table.get_entry(tr, ptid); + if(j == (field.argid - 1)) { - auto lineage = m_thread_table.get_entry(tr, ptid); - if(j == (field.argid - 1)) - { - m_exepath.read_value(tr, lineage, tstr); - break; - } - if(ptid == 1) - { - break; - } - m_ptid.read_value(tr, lineage, ptid); + m_exepath.read_value(tr, lineage, tstr); + break; } - catch(const std::exception& e) + if(ptid == 1) { + break; } + m_ptid.read_value(tr, lineage, ptid); + } + catch(const std::exception& e) + { } - break; } + break; + } case plugin_sinsp_filterchecks::TYPE_CWD: m_cwd.read_value(tr, thread_entry, tstr); break; @@ -534,35 +576,37 @@ bool anomalydetection::extract_filterchecks_concat_profile(int64_t thread_id, co break; } case plugin_sinsp_filterchecks::TYPE_APID: + { + if(field.argid < 1) { - if(field.argid < 1) - { - m_pid.read_value(tr, thread_entry, tint64); - break; - } - m_ptid.read_value(tr, thread_entry, ptid); - for(uint32_t j = 0; j < field.argid; j++) + m_pid.read_value(tr, thread_entry, tint64); + tstr = std::to_string(tint64); + break; + } + m_ptid.read_value(tr, thread_entry, ptid); + for(uint32_t j = 0; j < field.argid; j++) + { + try { - try + auto lineage = m_thread_table.get_entry(tr, ptid); + if(j == (field.argid - 1)) { - auto lineage = m_thread_table.get_entry(tr, ptid); - if(j == (field.argid - 1)) - { - m_pid.read_value(tr, lineage, tint64); - break; - } - if(ptid == 1) - { - break; - } - m_ptid.read_value(tr, lineage, ptid); + m_pid.read_value(tr, lineage, tint64); + tstr = std::to_string(tint64); + break; } - catch(const std::exception& e) + if(ptid == 1) { + break; } + m_ptid.read_value(tr, lineage, ptid); + } + catch(const std::exception& e) + { } - break; } + break; + } case plugin_sinsp_filterchecks::TYPE_VPID: m_vpid.read_value(tr, thread_entry, tint64); tstr = std::to_string(tint64); @@ -581,65 +625,65 @@ bool anomalydetection::extract_filterchecks_concat_profile(int64_t thread_id, co break; // todo better unit tests and double check the parent lineage traversal fields in general case plugin_sinsp_filterchecks::TYPE_SNAME: + { + int64_t sid; + m_sid.read_value(tr, thread_entry, sid); + m_ptid.read_value(tr, thread_entry, ptid); + falcosecurity::table_entry last_entry(nullptr, nullptr, nullptr); + falcosecurity::table_entry* leader = &thread_entry; + for(uint32_t j = 0; j < 9; j++) { - int64_t sid; - m_sid.read_value(tr, thread_entry, sid); - m_ptid.read_value(tr, thread_entry, ptid); - falcosecurity::table_entry last_entry(nullptr, nullptr, nullptr); - falcosecurity::table_entry* leader = &thread_entry; - for(uint32_t j = 0; j < 9; j++) + try { - try - { - auto lineage = m_thread_table.get_entry(tr, ptid); - m_sid.read_value(tr, lineage, tint64); - if(sid != tint64) - { - break; - } - m_ptid.read_value(tr, lineage, ptid); - last_entry = std::move(lineage); - leader = &last_entry; - } - catch(const std::exception& e) + auto lineage = m_thread_table.get_entry(tr, ptid); + m_sid.read_value(tr, lineage, tint64); + if(sid != tint64) { + break; } + m_ptid.read_value(tr, lineage, ptid); + last_entry = std::move(lineage); + leader = &last_entry; + } + catch(const std::exception& e) + { } - m_comm.read_value(tr, *leader, tstr); - break; } + m_comm.read_value(tr, *leader, tstr); + break; + } case plugin_sinsp_filterchecks::TYPE_VPGID: m_vpgid.read_value(tr, thread_entry, tint64); tstr = std::to_string(tint64); break; case plugin_sinsp_filterchecks::TYPE_VPGID_NAME: + { + int64_t vpgid; + m_vpgid.read_value(tr, thread_entry, vpgid); + m_ptid.read_value(tr, thread_entry, ptid); + falcosecurity::table_entry last_entry(nullptr, nullptr, nullptr); + falcosecurity::table_entry* leader = &thread_entry; + for(uint32_t j = 0; j < 5; j++) { - int64_t vpgid; - m_vpgid.read_value(tr, thread_entry, vpgid); - m_ptid.read_value(tr, thread_entry, ptid); - falcosecurity::table_entry last_entry(nullptr, nullptr, nullptr); - falcosecurity::table_entry* leader = &thread_entry; - for(uint32_t j = 0; j < 5; j++) + try { - try - { - auto lineage = m_thread_table.get_entry(tr, ptid); - m_vpgid.read_value(tr, lineage, tint64); - if(vpgid != tint64) - { - break; - } - m_ptid.read_value(tr, lineage, ptid); - last_entry = std::move(lineage); - leader = &last_entry; - } - catch(const std::exception& e) + auto lineage = m_thread_table.get_entry(tr, ptid); + m_vpgid.read_value(tr, lineage, tint64); + if(vpgid != tint64) { + break; } + m_ptid.read_value(tr, lineage, ptid); + last_entry = std::move(lineage); + leader = &last_entry; + } + catch(const std::exception& e) + { } - m_comm.read_value(tr, *leader, tstr); - break; } + m_comm.read_value(tr, *leader, tstr); + break; + } default: break; } diff --git a/plugins/anomalydetection/test/include/test_helpers.h b/plugins/anomalydetection/test/include/test_helpers.h index b5e5137e..6aeb37e1 100644 --- a/plugins/anomalydetection/test/include/test_helpers.h +++ b/plugins/anomalydetection/test/include/test_helpers.h @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -#define INIT_CONFIG "{\"count_min_sketch\":{\"enabled\":true,\"n_sketches\":3,\"gamma_eps\":[[0.001,0.0001],[0.001,0.0001],[0.001,0.0001]],\"behavior_profiles\":[{\"fields\":\"%container.id %proc.name %proc.aname[1] %proc.aname[2] %proc.aname[3] %proc.exepath %proc.pexepath %proc.aexepath[2] %proc.tty %proc.vpgid.name %proc.sname %proc.pid %proc.ppid %proc.sid %proc.vpgid %proc.vpid %proc.pvid %proc.apid[1]\",\"event_codes\":[293,331]},{\"fields\":\"%container.id %proc.name %proc.aname[1] %proc.aname[2] %proc.aname[3] %proc.exepath %proc.tty %proc.vpgid.name %proc.sname %fd.name\",\"event_codes\":[3,307,327]},{\"fields\":\"%container.id %proc.args\",\"event_codes\":[293,331]}]}}" +#define INIT_CONFIG "{\"count_min_sketch\":{\"enabled\":true,\"n_sketches\":3,\"gamma_eps\":[[0.001,0.0001],[0.001,0.0001],[0.001,0.0001]],\"behavior_profiles\":[{\"fields\":\"%container.id %proc.name %proc.pname %proc.exepath %proc.pexepath %proc.tty %proc.vpid %proc.pvid]\",\"event_codes\":[293,331]},{\"fields\":\"%container.id %proc.name %proc.aname[1] %proc.aname[2] %proc.aname[3] %proc.exepath %proc.tty %proc.vpgid.name %proc.sname %fd.name\",\"event_codes\":[3,307,327]},{\"fields\":\"%container.id %proc.cmdline %proc.name %proc.aname[0] %proc.aname[1] %proc.aname[2] %proc.aname[3] %proc.aname[4] %proc.aname[5] %proc.aname[6] %proc.aname[7] %proc.pid %proc.apid[0] %proc.apid[1] %proc.apid[2] %proc.apid[3] %proc.apid[4] %proc.apid[5] %proc.apid[6] %proc.apid[7] %proc.exepath %proc.aexepath[0] %proc.aexepath[1] %proc.aexepath[2] %proc.aexepath[3] %proc.aexepath[4] %proc.aexepath[5] %proc.aexepath[6] %proc.aexepath[7] %proc.vpgid %proc.vpgid.name %proc.sid %proc.sname\",\"event_codes\":[293,331]}]}}" #define ASSERT_PLUGIN_INITIALIZATION(p_o, p_l) \ { \ diff --git a/plugins/anomalydetection/test/src/num/cms.ut.cpp b/plugins/anomalydetection/test/src/num/cms.ut.cpp index 0b8bf832..3b329404 100644 --- a/plugins/anomalydetection/test/src/num/cms.ut.cpp +++ b/plugins/anomalydetection/test/src/num/cms.ut.cpp @@ -17,6 +17,7 @@ limitations under the License. #include #include +#include #include #include #include @@ -70,40 +71,67 @@ TEST_F(sinsp_with_test_input, plugin_anomalydetection_filterchecks_fields) add_default_init_thread(); open_inspector(); - + /* Create realistic spawn_process event, adopted from libs unit test */ sinsp_evt* evt = NULL; - uint64_t parent_pid = 1, parent_tid = 1, child_pid = 20, child_tid = 20, null_pid = 0; - uint64_t fdlimit = 1024, pgft_maj = 0, pgft_min = 1; - uint64_t exe_ino = 242048, ctime = 1676262698000004588, mtime = 1676262698000004577; - uint32_t loginuid = UINT32_MAX - 1, euid = 2000U; - scap_const_sized_buffer empty_bytebuf = {.buf = nullptr, .size = 0}; - - add_event_advance_ts(increasing_ts(), parent_tid, PPME_SYSCALL_CLONE_20_E, 0); - std::vector cgroups = {"cpuset=/", "cpu=/user.slice", "cpuacct=/user.slice", "io=/user.slice", "memory=/user.slice/user-1000.slice/session-1.scope", "devices=/user.slice", "freezer=/", "net_cls=/", "perf_event=/", "net_prio=/", "hugetlb=/", "pids=/user.slice/user-1000.slice/session-1.scope", "rdma=/", "misc=/"}; - std::string cgroupsv = test_utils::to_null_delimited(cgroups); - std::vector env = {"SHELL=/bin/bash", "SHELL_NEW=/bin/sh", "PWD=/home/user", "HOME=/home/user"}; - std::string envv = test_utils::to_null_delimited(env); - std::vector args = {"-c", "'echo aGVsbG8K | base64 -d'"}; - std::string argsv = test_utils::to_null_delimited(args); - - add_event_advance_ts(increasing_ts(), parent_tid, PPME_SYSCALL_CLONE_20_X, 20, parent_pid, "bash", empty_bytebuf, parent_pid, parent_tid, null_pid, "", fdlimit, pgft_maj, pgft_min, (uint32_t)12088, (uint32_t)7208, (uint32_t)0, "init", scap_const_sized_buffer{cgroupsv.data(), cgroupsv.size()}, (uint32_t)(PPM_CL_CLONE_CHILD_CLEARTID | PPM_CL_CLONE_CHILD_SETTID), (uint32_t)1000, (uint32_t)1000, parent_pid, parent_tid); - add_event_advance_ts(increasing_ts(), child_tid, PPME_SYSCALL_CLONE_20_X, 20, (uint64_t)0, "bash", empty_bytebuf, child_pid, child_tid, parent_tid, "", fdlimit, pgft_maj, pgft_min, (uint32_t)12088, (uint32_t)3764, (uint32_t)0, "init", scap_const_sized_buffer{cgroupsv.data(), cgroupsv.size()}, (uint32_t)(PPM_CL_CLONE_CHILD_CLEARTID | PPM_CL_CLONE_CHILD_SETTID), (uint32_t)1000, (uint32_t)1000, child_pid, child_tid); - add_event_advance_ts(increasing_ts(), child_tid, PPME_SYSCALL_EXECVE_19_E, 1, "/bin/test-exe"); - evt = add_event_advance_ts(increasing_ts(), child_tid, PPME_SYSCALL_EXECVE_19_X, 27, (int64_t)0, "/bin/test-exe", scap_const_sized_buffer{argsv.data(), argsv.size()}, child_tid, child_pid, parent_tid, "", fdlimit, pgft_maj, pgft_min, (uint32_t)29612, (uint32_t)4, (uint32_t)0, "test-exe", scap_const_sized_buffer{cgroupsv.data(), cgroupsv.size()}, scap_const_sized_buffer{envv.data(), envv.size()}, (int32_t)34818, parent_pid, loginuid, (int32_t) PPM_EXE_WRITABLE, parent_pid, parent_pid, parent_pid, exe_ino, ctime, mtime, euid); - - ASSERT_EQ(get_field_as_string(evt, "proc.name"), "test-exe"); - - // /* Check anomalydetection plugin filter fields */ + uint64_t parent_pid = 1, parent_tid = 1, child_pid = 20, child_tid = 20, null_pid = 0; + uint64_t fdlimit = 1024, pgft_maj = 0, pgft_min = 1; + uint64_t exe_ino = 242048, ctime = 1676262698000004588, mtime = 1676262698000004577; + uint32_t loginuid = UINT32_MAX - 1, euid = 2000U; + scap_const_sized_buffer empty_bytebuf = {.buf = nullptr, .size = 0}; + + add_event_advance_ts(increasing_ts(), parent_tid, PPME_SYSCALL_CLONE_20_E, 0); + std::vector cgroups = {"cpuset=/", "cpu=/user.slice", "cpuacct=/user.slice", "io=/user.slice", "memory=/user.slice/user-1000.slice/session-1.scope", "devices=/user.slice", "freezer=/", "net_cls=/", "perf_event=/", "net_prio=/", "hugetlb=/", "pids=/user.slice/user-1000.slice/session-1.scope", "rdma=/", "misc=/"}; + std::string cgroupsv = test_utils::to_null_delimited(cgroups); + std::vector env = {"SHELL=/bin/bash", "SHELL_NEW=/bin/sh", "PWD=/home/user", "HOME=/home/user"}; + std::string envv = test_utils::to_null_delimited(env); + std::vector args = {"-c", "'echo aGVsbG8K | base64 -d'"}; + std::string argsv = test_utils::to_null_delimited(args); + + add_event_advance_ts(increasing_ts(), parent_tid, PPME_SYSCALL_CLONE_20_X, 20, parent_pid, "bash", empty_bytebuf, parent_pid, parent_tid, null_pid, "", fdlimit, pgft_maj, pgft_min, (uint32_t)12088, (uint32_t)7208, (uint32_t)0, "init", scap_const_sized_buffer{cgroupsv.data(), cgroupsv.size()}, (uint32_t)(PPM_CL_CLONE_CHILD_CLEARTID | PPM_CL_CLONE_CHILD_SETTID), (uint32_t)1000, (uint32_t)1000, parent_pid, parent_tid); + add_event_advance_ts(increasing_ts(), child_tid, PPME_SYSCALL_CLONE_20_X, 20, (uint64_t)0, "bash", empty_bytebuf, child_pid, child_tid, parent_tid, "", fdlimit, pgft_maj, pgft_min, (uint32_t)12088, (uint32_t)3764, (uint32_t)0, "init", scap_const_sized_buffer{cgroupsv.data(), cgroupsv.size()}, (uint32_t)(PPM_CL_CLONE_CHILD_CLEARTID | PPM_CL_CLONE_CHILD_SETTID), (uint32_t)1000, (uint32_t)1000, child_pid, child_tid); + add_event_advance_ts(increasing_ts(), child_tid, PPME_SYSCALL_EXECVE_19_E, 1, "/bin/test-exe"); + evt = add_event_advance_ts(increasing_ts(), child_tid, PPME_SYSCALL_EXECVE_19_X, 27, (int64_t)0, "/bin/test-exe", scap_const_sized_buffer{argsv.data(), argsv.size()}, child_tid, child_pid, parent_tid, "", fdlimit, pgft_maj, pgft_min, (uint32_t)29612, (uint32_t)4, (uint32_t)0, "test-exe", scap_const_sized_buffer{cgroupsv.data(), cgroupsv.size()}, scap_const_sized_buffer{envv.data(), envv.size()}, (int32_t)34818, parent_pid, loginuid, (int32_t) PPM_EXE_WRITABLE, parent_pid, parent_pid, parent_pid, exe_ino, ctime, mtime, euid); + + ASSERT_EQ(get_field_as_string(evt, "proc.name"), "test-exe"); + + /* Check anomalydetection plugin filter fields */ ASSERT_TRUE(field_exists(evt, "anomaly.count_min_sketch", pl_flist)); ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch", pl_flist), "1"); ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch[0]", pl_flist), "1"); ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch[1]", pl_flist), "0"); - ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch[2]", pl_flist), "0"); + ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch[2]", pl_flist), "1"); ASSERT_TRUE(field_exists(evt, "anomaly.count_min_sketch.profile", pl_flist)); - ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile", pl_flist), "test-exeinit/bin/test-exe/sbin/init34818initinit2010120"); - ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[0]", pl_flist), "test-exeinit/bin/test-exe/sbin/init34818initinit2010120"); + ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile", pl_flist), "test-exeinit/bin/test-exe/sbin/init3481820"); + ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[0]", pl_flist), "test-exeinit/bin/test-exe/sbin/init3481820"); ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[1]", pl_flist), "test-exeinit/bin/test-exe34818initinit"); - ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[2]", pl_flist), ""); + ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[2]", pl_flist), "test-exe -c 'echo aGVsbG8K | base64 -d'test-exetest-exeinit20201/bin/test-exe/bin/test-exe/sbin/init1init0init"); +} + +TEST_F(sinsp_with_test_input, plugin_anomalydetection_filterchecks_fields_proc_lineage) +{ + std::shared_ptr plugin_owner; + filter_check_list pl_flist; + ASSERT_PLUGIN_INITIALIZATION(plugin_owner, pl_flist) + uint64_t not_relevant_64 = 0; + uint32_t not_relevant_32 = 0; + uint64_t pgid = 9999; + uint32_t loginuid = UINT32_MAX - 1, euid = 2000U; + scap_const_sized_buffer empty_bytebuf = {.buf = nullptr, .size = 0}; + std::vector args = {"-c", "'echo aGVsbG8K | base64 -d'"}; + std::string argsv = test_utils::to_null_delimited(args); + /* Instantiate the default tree */ + DEFAULT_TREE + generate_execve_enter_and_exit_event(0, p2_t1_tid, p2_t1_tid, p2_t1_pid, p2_t1_ptid, "/p2_t1_exepath", "p2_t1_comm", "/usr/bin/p2_t1_exepath"); + generate_execve_enter_and_exit_event(0, p3_t1_tid, p3_t1_tid, p3_t1_pid, p3_t1_ptid, "/p3_t1_exepath", "p3_t1_comm", "/usr/bin/p3_t1_exepath"); + generate_execve_enter_and_exit_event(0, p4_t1_tid, p4_t1_tid, p4_t1_pid, p4_t1_ptid, "/p4_t1_exepath", "p4_t1_comm", "/usr/bin/p4_t1_exepath"); + generate_execve_enter_and_exit_event(0, p4_t2_tid, p4_t1_tid, p4_t1_pid, p4_t1_ptid, "/p4_t1_exepath", "p4_t1_comm", "/usr/bin/p4_t1_exepath"); + + add_event_advance_ts(increasing_ts(), p5_t1_tid, PPME_SYSCALL_EXECVE_19_E, 1, "/usr/bin/p5_t1_exepath"); + add_event_advance_ts(increasing_ts(), p5_t1_tid, PPME_SYSCALL_EXECVE_19_X, 27, (int64_t)0, "/usr/bin/p5_t1_exepath", scap_const_sized_buffer{argsv.data(), argsv.size()}, p5_t1_tid, p5_t1_tid, p5_t1_ptid, "", not_relevant_64, not_relevant_64, not_relevant_64, (uint32_t)29612, (uint32_t)4, (uint32_t)0, "p5_t1_comm", empty_bytebuf, empty_bytebuf, (int32_t)34818, pgid, loginuid, (int32_t) PPM_EXE_WRITABLE, not_relevant_64, not_relevant_64, not_relevant_64, not_relevant_64, not_relevant_64, not_relevant_64, euid); + add_event_advance_ts(increasing_ts(), p6_t1_tid, PPME_SYSCALL_EXECVE_19_E, 1, "/usr/bin/p6_t1_exepath"); + auto evt = add_event_advance_ts(increasing_ts(), p6_t1_tid, PPME_SYSCALL_EXECVE_19_X, 27, (int64_t)0, "/usr/bin/p6_t1_exepath", scap_const_sized_buffer{argsv.data(), argsv.size()}, p6_t1_tid, p6_t1_tid, p6_t1_ptid, "", not_relevant_64, not_relevant_64, not_relevant_64, (uint32_t)29612, (uint32_t)4, (uint32_t)0, "p6_t1_comm", empty_bytebuf, empty_bytebuf, (int32_t)34818, pgid, loginuid, (int32_t) PPM_EXE_WRITABLE, not_relevant_64, not_relevant_64, not_relevant_64, not_relevant_64, not_relevant_64, not_relevant_64, euid); + + ASSERT_EQ(get_field_as_string(evt, "anomaly.count_min_sketch.profile[2]", pl_flist), "p6_t1_comm -c 'echo aGVsbG8K | base64 -d'p6_t1_commp6_t1_commp5_t1_commp4_t1_commp3_t1_commp2_t1_comminit8787827672251/usr/bin/p6_t1_exepath/usr/bin/p6_t1_exepath/usr/bin/p5_t1_exepath/usr/bin/p4_t1_exepath/usr/bin/p3_t1_exepath/usr/bin/p2_t1_exepath/sbin/init9999p5_t1_comm0init"); }