From da0685dbcccbe368e8d10fd8c6c621eaa912d016 Mon Sep 17 00:00:00 2001 From: Roberto Scolaro Date: Mon, 25 Nov 2024 18:47:54 +0000 Subject: [PATCH] fix(libsinsp): don't filter out procexit events Signed-off-by: Roberto Scolaro --- userspace/libsinsp/sinsp_suppress.cpp | 9 +- userspace/libsinsp/test/CMakeLists.txt | 1 + userspace/libsinsp/test/suppress.ut.cpp | 142 ++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 userspace/libsinsp/test/suppress.ut.cpp diff --git a/userspace/libsinsp/sinsp_suppress.cpp b/userspace/libsinsp/sinsp_suppress.cpp index 01ed82271fb..0a5a5c0c2ab 100644 --- a/userspace/libsinsp/sinsp_suppress.cpp +++ b/userspace/libsinsp/sinsp_suppress.cpp @@ -120,12 +120,13 @@ int32_t libsinsp::sinsp_suppress::process_event(scap_evt *e) { case PPME_PROCEXIT_1_E: { auto it = m_suppressed_tids.find(tid); if(it != m_suppressed_tids.end()) { + // Given that the process is exiting, we remove the + // tid from the suppressed tids. m_suppressed_tids.erase(it); - m_num_suppressed_events++; - return SCAP_FILTERED_EVENT; - } else { - return SCAP_SUCCESS; } + // We don't filter out procexit event otherwise + // we'll keep stale threadinfo in the threadtable. + return SCAP_SUCCESS; } default: diff --git a/userspace/libsinsp/test/CMakeLists.txt b/userspace/libsinsp/test/CMakeLists.txt index fd7a521227a..84e9e4f9bee 100644 --- a/userspace/libsinsp/test/CMakeLists.txt +++ b/userspace/libsinsp/test/CMakeLists.txt @@ -108,6 +108,7 @@ set(LIBSINSP_UNIT_TESTS_SOURCES user.ut.cpp sinsp_utils.ut.cpp state.ut.cpp + suppress.ut.cpp dns_manager.ut.cpp eventformatter.ut.cpp sinsp_metrics.ut.cpp diff --git a/userspace/libsinsp/test/suppress.ut.cpp b/userspace/libsinsp/test/suppress.ut.cpp new file mode 100644 index 00000000000..3d56fd411c1 --- /dev/null +++ b/userspace/libsinsp/test/suppress.ut.cpp @@ -0,0 +1,142 @@ +// SPDX-License-Identifier: Apache-2.0 +/* +Copyright (C) 2024 The Falco Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +*/ + +#include +#include + +#include +#include + +#define generate_execve_x(pid, file_to_run, comm) \ + add_event_advance_ts(increasing_ts(), \ + pid, \ + PPME_SYSCALL_EXECVE_19_X, \ + 29, \ + (int64_t)0, /* res */ \ + file_to_run, /* exe */ \ + (scap_const_sized_buffer){nullptr, 0}, /* args */ \ + (uint64_t)pid, /* tid */ \ + (uint64_t)pid, /* pid */ \ + (uint64_t)pid, /* ptid */ \ + "", /* cwd */ \ + (uint64_t)0, /* fdlimit */ \ + (uint64_t)0, /* pgft_maj */ \ + (uint64_t)0, /* pgft_min */ \ + 0, /* vm_size */ \ + 0, /* vm_rss */ \ + 0, /* vm_swap */ \ + comm, /* comm */ \ + (scap_const_sized_buffer){nullptr, 0}, /* cgroups */ \ + (scap_const_sized_buffer){nullptr, 0}, /* env */ \ + 0, /* tty */ \ + (uint64_t)0, /* vpgid */ \ + 0, /* loginuid */ \ + 0, /* flags */ \ + (uint64_t)0, /* cap_inheritable */ \ + (uint64_t)0, /* cap_permitted */ \ + (uint64_t)0, /* cap_effective */ \ + (uint64_t)0, /* exe_ino */ \ + (uint64_t)0, /* exe_ino_ctime */ \ + (uint64_t)0, /* exe_ino_mtime */ \ + (uint32_t)0, /* uid */ \ + "", /* trusted_exepath */ \ + (uint64_t)0) /* pgid */ + +TEST_F(sinsp_with_test_input, suppress_comm) { + // + // init (pid 1) + // └── sh (pid 17) + // + + add_default_init_thread(); + + m_inspector.clear_suppress_events_comm(); + m_inspector.suppress_events_comm("sh"); + + open_inspector(); + + uint64_t pid = 17; + generate_clone_x_event(pid, INIT_TID, INIT_TID, INIT_TID); + + const char* file_to_run = "/bin/sh"; + + add_event_advance_ts(increasing_ts(), pid, PPME_SYSCALL_EXECVE_19_E, 1, file_to_run); + + EXPECT_ANY_THROW(generate_execve_x(pid, file_to_run, "sh")); + + add_event_advance_ts(increasing_ts(), pid, PPME_PROCEXIT_1_E, 0); + + // dummy event to actually delete the thread from the threadtable. + add_event_advance_ts(increasing_ts(), INIT_TID, PPME_SYSCALL_RENAME_E, 0); + + auto tinfo = m_inspector.get_thread_ref(pid); + + EXPECT_EQ(tinfo, nullptr); + + scap_stats st; + m_inspector.get_capture_stats(&st); + EXPECT_EQ(st.n_suppressed, 1); + EXPECT_EQ(st.n_tids_suppressed, 0); +} + +TEST_F(sinsp_with_test_input, suppress_comm_execve) { + // + // init (pid 1) + // └── sh (pid 17) + // + // then sh calls execve + // + // init (pid 1) + // └── /bin/test-exe (pid 17) + // + + add_default_init_thread(); + + m_inspector.clear_suppress_events_comm(); + m_inspector.suppress_events_comm("sh"); + + open_inspector(); + + uint64_t pid = 17; + generate_clone_x_event(pid, INIT_TID, INIT_TID, INIT_TID); + + const char* file_to_run = "/bin/sh"; + add_event_advance_ts(increasing_ts(), pid, PPME_SYSCALL_EXECVE_19_E, 1, file_to_run); + EXPECT_ANY_THROW(generate_execve_x(pid, file_to_run, "sh")); + + EXPECT_ANY_THROW(add_event_advance_ts(increasing_ts(), + pid, + PPME_SYSCALL_EXECVE_19_E, + 1, + "/bin/test-exe")); + EXPECT_ANY_THROW(generate_execve_x(pid, "/bin/test-exe", "test-exe")); + + add_event_advance_ts(increasing_ts(), pid, PPME_PROCEXIT_1_E, 0); + + // dummy event to actually delete the thread from the threadtable. + add_event_advance_ts(increasing_ts(), INIT_TID, PPME_SYSCALL_RENAME_E, 0); + + auto tinfo = m_inspector.get_thread_ref(pid); + + EXPECT_EQ(tinfo, nullptr); + + scap_stats st; + m_inspector.get_capture_stats(&st); + EXPECT_EQ(st.n_suppressed, 3); + EXPECT_EQ(st.n_tids_suppressed, 0); +}