diff --git a/driver/modern_bpf/helpers/store/auxmap_store_params.h b/driver/modern_bpf/helpers/store/auxmap_store_params.h index 5887b63d04..b9016f3006 100644 --- a/driver/modern_bpf/helpers/store/auxmap_store_params.h +++ b/driver/modern_bpf/helpers/store/auxmap_store_params.h @@ -1303,7 +1303,7 @@ static __always_inline uint16_t store_cgroup_subsys(struct auxiliary_map *auxmap * at the end of the string, reading with `bpf_probe_read_str()`). * * The rationale here is to replace the string terminator '\0' - * with the '/' for every path compotent, excluding the last. + * with the '/' for every path component, excluding the last. * * Starting from what we have already inserted ("cpuset="), * we want to obtain as a final result: @@ -1323,6 +1323,39 @@ static __always_inline uint16_t store_cgroup_subsys(struct auxiliary_map *auxmap * * cpuset=/path_part1/path_part2\0 */ + + /* + * If kernfs node is still not NULL, it means last path component retrieved + * (ie: the first one to be printed) was still not '\0' (ie: '/'). + * To avoid sending a cgroup that does not start with '/', manually add it. + * + * Example: + * /user.slice/user-1000.slice/user@1000.service/app.slice/app-org.gnome.Terminal.slice/vte-spawn-2f17b2eb-994e-415d-bce0-44c1447d7cd2.scope + * gets split as: + * * vte-spawn-2f17b2eb-994e-415d-bce0-44c1447d7cd2.scope\0 + * * app-org.gnome.Terminal.slice\0 + * * app.slice\0 + * * user@1000.service\0 + * * user-1000.slice\0 + * * user.slice\0 + * Without the below fix, we would send to userspace "user.slice/user-1000.slice/..." without + * leading '/'. + * + * Counter example with "5" components + the root: + * /user.slice/user-1000.slice/user@1000.service/app.slice/app-org.gnome.Terminal.slice + * gets split as: + * * app-org.gnome.Terminal.slice\0 + * * app.slice\0 + * * user@1000.service\0 + * * user-1000.slice\0 + * * user.slice\0 + * * \0 + * In this case, we won't push the new character, instead we will push the correct string. + */ + if(kn) { + push__new_character(auxmap->data, &auxmap->payload_pos, '/'); + total_size++; + } for(int k = MAX_CGROUP_PATH_POINTERS - 1; k >= 0; --k) { if(cgroup_path_pointers[k]) { total_size += push__charbuf(auxmap->data, diff --git a/test/libsinsp_e2e/capture_to_file_test.cpp b/test/libsinsp_e2e/capture_to_file_test.cpp index 0627501451..dbe4c4d713 100644 --- a/test/libsinsp_e2e/capture_to_file_test.cpp +++ b/test/libsinsp_e2e/capture_to_file_test.cpp @@ -32,7 +32,7 @@ TEST_F(sys_call_test, can_consume_a_capture_file) { evt->get_direction() == SCAP_ED_OUT; }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = [](sinsp* inspector) { struct stat sb; for(int i = 0; i < 100; i++) { stat("/tmp", &sb); diff --git a/test/libsinsp_e2e/container/container.cpp b/test/libsinsp_e2e/container/container.cpp index 195f2b6a37..7d22be2433 100644 --- a/test/libsinsp_e2e/container/container.cpp +++ b/test/libsinsp_e2e/container/container.cpp @@ -33,14 +33,15 @@ TEST_F(sys_call_test, container_cgroups) { // // FILTER // - event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_tid() == ctid; }; + event_filter_t filter = [&](sinsp_evt* evt) { + return evt->get_type() == PPME_SYSCALL_CLONE_20_X && evt->get_tid() == ctid; + }; // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_async_t test = [&]() { ctid = fork(); - if(ctid >= 0) { if(ctid == 0) { sleep(1); @@ -55,70 +56,69 @@ TEST_F(sys_call_test, container_cgroups) { }; // - // OUTPUT VALDATION + // OUTPUT VALIDATION // captured_event_callback_t callback = [&](const callback_param& param) { - if(param.m_evt->get_type() == PPME_SYSCALL_CLONE_20_X) { - sinsp_threadinfo sinsp_tinfo(nullptr); - char buf[100]; + sinsp_threadinfo sinsp_tinfo(nullptr); + char buf[100]; - sinsp_threadinfo* tinfo = param.m_evt->get_thread_info(); - ASSERT_TRUE(tinfo != NULL); - const auto& cgroups = tinfo->cgroups(); - ASSERT_TRUE(cgroups.size() > 0); + sinsp_threadinfo* tinfo = param.m_evt->get_thread_info(); + ASSERT_TRUE(tinfo != nullptr); + const auto& cgroups = tinfo->cgroups(); + ASSERT_TRUE(!cgroups.empty()); - snprintf(buf, sizeof(buf), "/proc/%d/", ctid); + snprintf(buf, sizeof(buf), "/proc/%d/", ctid); - sinsp_tinfo.m_tid = ctid; - sinsp_cgroup::instance().lookup_cgroups(sinsp_tinfo); + sinsp_tinfo.m_tid = ctid; + sinsp_cgroup::instance().lookup_cgroups(sinsp_tinfo); - const auto& sinsp_cgroups = sinsp_tinfo.cgroups(); - ASSERT_TRUE(sinsp_cgroups.size() > 0); + const auto& sinsp_cgroups = sinsp_tinfo.cgroups(); + ASSERT_TRUE(!sinsp_cgroups.empty()); - map cgroups_kernel; - for(uint32_t j = 0; j < cgroups.size(); ++j) { - cgroups_kernel.insert(pair(cgroups[j].first, cgroups[j].second)); - } + map cgroups_kernel; + for(const auto& cgroup : cgroups) { + cgroups_kernel.insert(pair(cgroup.first, cgroup.second)); + } - map cgroups_proc; - for(uint32_t j = 0; j < sinsp_cgroups.size(); ++j) { - cgroups_proc.insert( - pair(sinsp_cgroups[j].first, sinsp_cgroups[j].second)); - } + map cgroups_proc; + for(const auto& sinsp_cgroup : sinsp_cgroups) { + cgroups_proc.insert(pair(sinsp_cgroup.first, sinsp_cgroup.second)); + } - ASSERT_TRUE(cgroups_kernel.size() > 0); - ASSERT_TRUE(cgroups_proc.size() > 0); + ASSERT_TRUE(!cgroups_kernel.empty()); + ASSERT_TRUE(!cgroups_proc.empty()); - for(const auto& [subsys, path] : cgroups_proc) { - printf(" proc cgroup[%s] == <%s>\n", subsys.c_str(), path.c_str()); - } + for(const auto& [subsys, path] : cgroups_proc) { + printf(" proc cgroup[%s] == <%s>\n", subsys.c_str(), path.c_str()); + } - for(const auto& [subsys, path] : cgroups_kernel) { - printf(" kernel cgroup[%s] == <%s>\n", subsys.c_str(), path.c_str()); - } + for(const auto& [subsys, path] : cgroups_kernel) { + printf(" kernel cgroup[%s] == <%s>\n", subsys.c_str(), path.c_str()); + } - for(auto& [proc_subsys, proc_path] : cgroups_proc) { - auto it_kernel = cgroups_kernel.find(proc_subsys); - if(it_kernel != cgroups_kernel.end()) { - EXPECT_EQ(it_kernel->first, proc_subsys); - EXPECT_EQ(it_kernel->second, proc_path); - } + for(auto& [proc_subsys, proc_path] : cgroups_proc) { + auto it_kernel = cgroups_kernel.find(proc_subsys); + if(it_kernel != cgroups_kernel.end()) { + ASSERT_EQ(it_kernel->first, proc_subsys); + ASSERT_EQ(it_kernel->second, proc_path); } - - done = true; } + + done = true; }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); ASSERT_TRUE(done); } static int clone_callback(void* arg) { - // Here we need 2 sleeps instead of once because, for some reason, - // we miss the first one. This problem is *probably* related to the - // fact that before we created a brand new inspector for each test but - // not we keep the same and start/stop the capture. - sleep(1); sleep(1); return 0; } @@ -136,7 +136,7 @@ TEST_F(sys_call_test, container_clone_nspid) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { const int STACK_SIZE = 65536; /* Stack size for cloned child */ char* stack; /* Start of stack buffer area */ char* stack_top; /* End of stack buffer area */ @@ -174,7 +174,14 @@ TEST_F(sys_call_test, container_clone_nspid) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); ASSERT_TRUE(done); } @@ -183,21 +190,6 @@ TEST_F(sys_call_test, container_clone_nspid_ioctl) { int flags = CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | SIGCHLD | CLONE_NEWPID; bool done = false; - const int STACK_SIZE = 65536; - char* stack; - char* stack_top; - - stack = (char*)malloc(STACK_SIZE); - if(stack == NULL) { - FAIL(); - } - stack_top = stack + STACK_SIZE; - - ctid = clone(clone_callback, stack_top, flags, NULL); - if(ctid == -1) { - FAIL(); - } - // // FILTER // @@ -206,8 +198,23 @@ TEST_F(sys_call_test, container_clone_nspid_ioctl) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { + const int STACK_SIZE = 65536; + char* stack; + char* stack_top; + + stack = (char*)malloc(STACK_SIZE); + if(stack == NULL) { + FAIL(); + } + stack_top = stack + STACK_SIZE; + + ctid = clone(clone_callback, stack_top, flags, NULL); + if(ctid == -1) { + FAIL(); + } waitpid(ctid, NULL, 0); + free(stack); }; // @@ -220,8 +227,14 @@ TEST_F(sys_call_test, container_clone_nspid_ioctl) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); - free(stack); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); ASSERT_TRUE(done); } @@ -238,7 +251,7 @@ static void run_container_docker_test(bool fork_after_container_start) { evt->get_type() == PPME_CONTAINER_JSON_2_E); }; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_async_t test = [&]() { ASSERT_TRUE(system("docker kill libsinsp_docker > /dev/null 2>&1 || true") == 0); ASSERT_TRUE(system("docker rm -v libsinsp_docker > /dev/null 2>&1 || true") == 0); @@ -293,7 +306,14 @@ static void run_container_docker_test(bool fork_after_container_start) { done = true; }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); ASSERT_TRUE(done); } @@ -331,7 +351,7 @@ TEST_F(sys_call_test, container_docker_bad_socket) { return; } - before_open_t setup = [&](sinsp* inspector) { + before_capture_t setup = [&](sinsp* inspector) { inspector->set_docker_socket_path("/invalid/path"); }; @@ -346,7 +366,7 @@ TEST_F(sys_call_test, container_docker_bad_socket) { return false; }; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_async_t test = []() { ASSERT_TRUE(system("docker kill libsinsp_docker > /dev/null 2>&1 || true") == 0); ASSERT_TRUE(system("docker rm -v libsinsp_docker > /dev/null 2>&1 || true") == 0); @@ -383,7 +403,7 @@ TEST_F(sys_call_test, container_docker_bad_socket) { } }; - before_close_t cleanup = [&](sinsp* inspector) { + after_capture_t cleanup = [&](sinsp* inspector) { inspector->set_docker_socket_path("/var/run/docker.sock"); }; @@ -399,16 +419,8 @@ TEST_F(sys_call_test, container_libvirt) { return; } - event_filter_t filter = [&](sinsp_evt* evt) { - sinsp_threadinfo* tinfo = evt->get_thread_info(); - if(tinfo) { - return !tinfo->m_container_id.empty() && tinfo->m_comm == "sh"; - } - - return false; - }; - - run_callback_t test = [&](concurrent_object_handle inspector) { + // Setup phase before capture has start, to avoid generating too many events + before_capture_t setup = [](sinsp* inspector) { FILE* f = fopen("/tmp/conf.xml", "w"); ASSERT_TRUE(f != NULL); fprintf(f, @@ -434,15 +446,21 @@ TEST_F(sys_call_test, container_libvirt) { if(system("virsh -c lxc:/// define /tmp/conf.xml") != 0) { ASSERT_TRUE(false); } + }; + + event_filter_t filter = [&](sinsp_evt* evt) { + sinsp_threadinfo* tinfo = evt->get_thread_info(); + if(tinfo) { + return !tinfo->m_container_id.empty() && tinfo->m_comm == "sh"; + } + return false; + }; + run_callback_async_t test = []() { if(system("virsh -c lxc:/// start libvirt-container") != 0) { ASSERT_TRUE(false); } - sleep(2); - - ASSERT_TRUE(system("virsh -c lxc:/// undefine libvirt-container > /dev/null 2>&1") == 0); - ASSERT_TRUE(system("virsh -c lxc:/// destroy libvirt-container > /dev/null 2>&1") == 0); }; captured_event_callback_t callback = [&](const callback_param& param) { @@ -467,7 +485,19 @@ TEST_F(sys_call_test, container_libvirt) { done = true; }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + after_capture_t cleanup = [](sinsp* inspector) { + ASSERT_TRUE(system("virsh -c lxc:/// undefine libvirt-container > /dev/null 2>&1") == 0); + ASSERT_TRUE(system("virsh -c lxc:/// destroy libvirt-container > /dev/null 2>&1") == 0); + }; + + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + setup, + cleanup, + libsinsp::events::sinsp_state_sc_set()); + }); ASSERT_TRUE(done); } @@ -486,18 +516,6 @@ class container_state { bool healthcheck_seen; }; -static std::string capture_stats(sinsp* inspector) { - scap_stats st; - inspector->get_capture_stats(&st); - - std::stringstream ss; - - ss << "capture stats: dropped=" << st.n_drops << " buf=" << st.n_drops_buffer - << " pf=" << st.n_drops_pf << " bug=" << st.n_drops_bug; - - return ss.str(); -} - static void update_container_state(sinsp* inspector, sinsp_evt* evt, container_state& cstate, @@ -528,8 +546,7 @@ static void update_container_state(sinsp* inspector, if(!cstate.root_cmd_seen) { cstate.root_cmd_seen = true; - ASSERT_EQ(tinfo->m_category, sinsp_threadinfo::CAT_CONTAINER) - << capture_stats(inspector); + ASSERT_EQ(tinfo->m_category, sinsp_threadinfo::CAT_CONTAINER); } else { // In some cases, it can take so long for the async fetch of container info to // complete (1.5 seconds) that a healthcheck proc might be run before the container @@ -537,7 +554,7 @@ static void update_container_state(sinsp* inspector, // the container info has a health probe. if(cstate.container_w_health_probe) { cstate.healthcheck_seen = true; - ASSERT_EQ(tinfo->m_category, expected_cat) << capture_stats(inspector); + ASSERT_EQ(tinfo->m_category, expected_cat); } } } @@ -547,13 +564,12 @@ static void update_container_state(sinsp* inspector, if(cmdline == "sleep 10") { if(!cstate.second_cmd_seen) { cstate.second_cmd_seen = true; - ASSERT_EQ(tinfo->m_category, sinsp_threadinfo::CAT_CONTAINER) - << capture_stats(inspector); + ASSERT_EQ(tinfo->m_category, sinsp_threadinfo::CAT_CONTAINER); } else { // See above caveat about slow container info fetches if(cstate.container_w_health_probe) { // Should inherit container healthcheck property from parent. - ASSERT_EQ(tinfo->m_category, expected_cat) << capture_stats(inspector); + ASSERT_EQ(tinfo->m_category, expected_cat); } } } @@ -563,7 +579,7 @@ static void update_container_state(sinsp* inspector, if(cmdline == "ut-health-check" || cmdline == "sh -c /bin/ut-health-check") { cstate.healthcheck_seen = true; - ASSERT_EQ(tinfo->m_category, expected_cat) << capture_stats(inspector); + ASSERT_EQ(tinfo->m_category, expected_cat); } } } @@ -579,8 +595,7 @@ static void healthcheck_helper( std::vector& labels, sinsp_threadinfo::command_category expected_cat = sinsp_threadinfo::CAT_HEALTHCHECK) { container_state cstate; - bool exited_early = false; - std::string capture_stats_str = "(Not Collected Yet)"; + std::atomic exited_early = false; if(!dutils_check_docker()) { return; @@ -597,24 +612,14 @@ static void healthcheck_helper( ASSERT_TRUE(dhelper.build_image() == 0); - before_open_t setup = [&](sinsp* inspector) {}; - event_filter_t filter = [&](sinsp_evt* evt) { sinsp_threadinfo* tinfo = evt->get_thread_info(); - return (strcmp(evt->get_name(), "execve") == 0 && evt->get_direction() == SCAP_ED_OUT && - tinfo->m_container_id != ""); + return (tinfo != nullptr && strcmp(evt->get_name(), "execve") == 0 && + evt->get_direction() == SCAP_ED_OUT && !tinfo->m_container_id.empty()); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { - // Setting dropping mode preserves the execs but - // reduces the chances that we'll drop events during - // the docker fetch. - { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->start_dropping_mode(1); - } - + run_callback_async_t test = [&]() { int rc = dhelper.run_container("cont_health_ut", "/bin/sh -c '/bin/sleep 10'"); ASSERT_TRUE(exited_early || (rc == 0)); @@ -632,17 +637,19 @@ static void healthcheck_helper( } }; - before_close_t cleanup = [&](sinsp* inspector) { - capture_stats_str = capture_stats(inspector); - inspector->stop_dropping_mode(); - }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); - - ASSERT_TRUE(cstate.root_cmd_seen) << capture_stats_str; - ASSERT_TRUE(cstate.second_cmd_seen) << capture_stats_str; - ASSERT_EQ(cstate.container_w_health_probe, expect_healthcheck) << capture_stats_str; - ASSERT_EQ(cstate.healthcheck_seen, expect_healthcheck) << capture_stats_str; + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); + + ASSERT_TRUE(cstate.root_cmd_seen); + ASSERT_TRUE(cstate.second_cmd_seen); + ASSERT_EQ(cstate.container_w_health_probe, expect_healthcheck); + ASSERT_EQ(cstate.healthcheck_seen, expect_healthcheck); } static void healthcheck_tracefile_helper( @@ -657,7 +664,7 @@ static void healthcheck_tracefile_helper( dockerfile + " . > /dev/null 2>&1"); ASSERT_TRUE(system(build_cmdline.c_str()) == 0); - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_async_t test = []() { // --network=none speeds up the container setup a bit. ASSERT_TRUE( (system("docker run --rm --network=none --name cont_health_ut cont_health_ut_img " @@ -671,7 +678,14 @@ static void healthcheck_tracefile_helper( captured_event_callback_t callback = [&](const callback_param& param) { return; }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); // Now reread the file we just wrote and pass it through // update_container_state. @@ -687,7 +701,7 @@ static void healthcheck_tracefile_helper( inspector.open_savefile(dumpfile); inspector.start_capture(); - while(1) { + while(true) { sinsp_evt* ev; int32_t res = inspector.next(&ev); @@ -704,7 +718,7 @@ static void healthcheck_tracefile_helper( update_container_state(&inspector, ev, cstate, expected_cat); } - std::string capture_stats_str = capture_stats(&inspector); + std::string capture_stats_str = event_capture::capture_stats(&inspector); inspector.stop_capture(); inspector.close(); @@ -819,19 +833,17 @@ TEST_F(sys_call_test, docker_container_large_json) { ASSERT_TRUE(dhelper.build_image() == 0); + before_capture_t before = [&](sinsp* inspector) { + inspector->set_container_labels_max_len(60000); + }; + event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_type() == PPME_CONTAINER_JSON_E || evt->get_type() == PPME_CONTAINER_JSON_2_E; }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { - // set container label max to huge value - { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->set_container_labels_max_len(60000); - } + run_callback_async_t test = [&]() { int rc = dhelper.run_container("large_container_ut", "/bin/sh -c '/bin/sleep 3'"); - ASSERT_TRUE(rc == 0); }; @@ -868,11 +880,20 @@ TEST_F(sys_call_test, docker_container_large_json) { } EXPECT_TRUE(labels.empty()); + }; + after_capture_t cleanup = [](sinsp* inspector) { // reset the value - param.m_inspector->set_container_labels_max_len(100); + inspector->set_container_labels_max_len(100); }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + before, + cleanup, + libsinsp::events::sinsp_state_sc_set()); + }); ASSERT_TRUE(saw_container_evt); } diff --git a/test/libsinsp_e2e/event_capture.cpp b/test/libsinsp_e2e/event_capture.cpp index 5face207e8..748d34accd 100644 --- a/test/libsinsp_e2e/event_capture.cpp +++ b/test/libsinsp_e2e/event_capture.cpp @@ -24,208 +24,135 @@ limitations under the License. #include #include #include - -std::string event_capture::m_engine_string = KMOD_ENGINE; -std::string event_capture::m_engine_path = ""; -unsigned long event_capture::m_buffer_dim = DEFAULT_DRIVER_BUFFER_BYTES_DIM; -bool event_capture::inspector_ok = false; - -concurrent_object_handle event_capture::get_inspector_handle() { - return {get_inspector(), m_inspector_mutex}; +#include + +std::string event_capture::s_engine_string = KMOD_ENGINE; +std::string event_capture::s_engine_path; +unsigned long event_capture::s_buffer_dim = DEFAULT_DRIVER_BUFFER_BYTES_DIM * 4; + +event_capture::event_capture(captured_event_callback_t captured_event_callback, + before_capture_t before_open, + after_capture_t before_close, + event_filter_t filter, + uint32_t max_thread_table_size, + uint64_t thread_timeout_ns, + uint64_t inactive_thread_scan_time_ns) { + m_captured_event_callback = std::move(captured_event_callback); + m_before_capture = std::move(before_open); + m_after_capture = std::move(before_close); + m_filter = std::move(filter); + + m_eventfd = -1; + m_leaving = false; + + m_inspector = std::make_unique(); + m_inspector->m_thread_manager->set_max_thread_table_size(max_thread_table_size); + m_inspector->m_thread_timeout_ns = thread_timeout_ns; + m_inspector->set_auto_threads_purging_interval_s(inactive_thread_scan_time_ns); + m_inspector->set_auto_threads_purging(false); + m_inspector->set_debug_mode(true); + m_inspector->set_hostname_and_port_resolution_mode(false); + + m_param.m_inspector = m_inspector.get(); } -void event_capture::init_inspector() { - get_inspector()->m_thread_manager->set_max_thread_table_size(m_max_thread_table_size); - get_inspector()->m_thread_timeout_ns = m_thread_timeout_ns; - get_inspector()->set_auto_threads_purging_interval_s(m_inactive_thread_scan_time_ns); - get_inspector()->set_auto_threads_purging(false); - - get_inspector()->set_get_procs_cpu_from_driver(true); - - ASSERT_FALSE(get_inspector()->is_capture()); - ASSERT_FALSE(get_inspector()->is_live()); - ASSERT_FALSE(get_inspector()->is_nodriver()); +void event_capture::start(bool dump, libsinsp::events::set& sc_set) { + m_eventfd = eventfd(0, EFD_NONBLOCK); - try { - if(m_mode == SINSP_MODE_NODRIVER) { - get_inspector()->open_nodriver(); - } else { - open_engine(event_capture::get_engine(), {}); - } - } catch(sinsp_exception& e) { - m_start_failed = true; - m_start_failure_message = - "couldn't open inspector (maybe driver hasn't been loaded yet?) err=" + - get_inspector()->getlasterr() + " exception=" + e.what(); - { - m_capture_started = true; - m_condition_started.notify_one(); + // To avoid back-pressure on the eventfd reads, do not attach them. + if(sc_set.empty()) { + for(int i = 0; i < PPM_SC_MAX; i++) { + auto sc_code = (ppm_sc_code)i; + if(sc_code != PPM_SC_READ && sc_code != PPM_SC_READV) { + sc_set.insert(sc_code); + } } - return; } + open_engine(event_capture::get_engine(), sc_set); - get_inspector()->set_debug_mode(true); - get_inspector()->set_hostname_and_port_resolution_mode(false); -} - -void event_capture::capture() { const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); - std::unique_ptr dumper; - { - std::scoped_lock init_lock(m_inspector_mutex, m_object_state_mutex); - - if(!inspector_ok) { - init_inspector(); - if(!m_start_failed) { - inspector_ok = true; - } else { - std::cerr << m_start_failure_message << std::endl; - return; - } - } + if(dump) { + auto dump_filename = std::string(LIBSINSP_TEST_CAPTURES_PATH) + + test_info->test_case_name() + "_" + test_info->name() + ".scap"; + m_dumper = std::make_unique(m_inspector.get(), + dump_filename.c_str(), + 0, + 0, + 0, + 0, + true); + } - m_param.m_inspector = get_inspector(); - - m_before_open(get_inspector()); - - get_inspector()->start_capture(); - if(m_mode != SINSP_MODE_NODRIVER) { - m_dump_filename = std::string(LIBSINSP_TEST_CAPTURES_PATH) + - test_info->test_case_name() + "_" + test_info->name() + ".scap"; - dumper = std::make_unique(get_inspector(), - m_dump_filename.c_str(), - 0, - 0, - 0, - 0, - true); - } - } // End init synchronized section + m_before_capture(m_inspector.get()); + m_inspector->start_capture(); +} + +void event_capture::stop() { + close(m_eventfd); + m_inspector->stop_capture(); + m_after_capture(m_inspector.get()); + if(m_dumper != nullptr) { + m_dumper->close(); + } + m_inspector->close(); +} - bool signaled_start = false; +void event_capture::capture() { sinsp_evt* event; bool result = true; int32_t next_result = SCAP_SUCCESS; + + /* + * Loop until: + * * test has non fatal failures + * * handle_event returns true + * * we weren't asked to leave from eventfd and we received !SCAP_SUCCESS + */ while(result && !::testing::Test::HasFatalFailure()) { - { - std::lock_guard lock(m_object_state_mutex); - if(m_capture_stopped) { - break; - } - } - { - std::scoped_lock inspector_next_lock(m_inspector_mutex); - next_result = get_inspector()->next(&event); + handle_eventfd_request(); + next_result = m_inspector->next(&event); + if(next_result == SCAP_FILTERED_EVENT) { + continue; } - if(SCAP_SUCCESS == next_result) { - result = handle_event(event); - if(m_mode != SINSP_MODE_NODRIVER && m_dump) { - dumper->dump(event); + if(next_result == SCAP_SUCCESS) { + if(m_dumper != nullptr) { + m_dumper->dump(event); } - } - if(!signaled_start) { - signaled_start = true; - { - std::lock_guard lock(m_object_state_mutex); - m_capture_started = true; - } - m_condition_started.notify_one(); + result = handle_event(event); + } else if(m_leaving) { + break; } } - if(m_mode != SINSP_MODE_NODRIVER) { - uint32_t n_timeouts = 0; - while(result && !::testing::Test::HasFatalFailure()) { - { - std::scoped_lock inspector_next_lock(m_inspector_mutex); - next_result = get_inspector()->next(&event); - } - if(next_result == SCAP_TIMEOUT) { - n_timeouts++; - - if(n_timeouts < m_max_timeouts) { - continue; - } else { - break; - } - } - - if(next_result == SCAP_FILTERED_EVENT) { - continue; - } - if(next_result != SCAP_SUCCESS) { - break; - } - if(m_dump) { - dumper->dump(event); + /* + * Second loop to empty the buffers from all the generated events: + * * loop until SCAP_TIMEOUT is received. + */ + result = true; + while(result) { + next_result = m_inspector->next(&event); + if(next_result == SCAP_SUCCESS) { + if(m_dumper != nullptr) { + m_dumper->dump(event); } result = handle_event(event); - } - { - std::scoped_lock inspector_next_lock(m_inspector_mutex); - while(SCAP_SUCCESS == get_inspector()->next(&event)) { - // just consume the remaining events - } + } else if(next_result == SCAP_TIMEOUT) { + break; } } - { // Begin teardown synchronized section - std::scoped_lock teardown_lock(m_inspector_mutex, m_object_state_mutex); - m_before_close(get_inspector()); - - get_inspector()->stop_capture(); - if(m_mode != SINSP_MODE_NODRIVER) { - dumper->close(); - } - - m_capture_stopped = true; - } // End teardown synchronized section - - m_condition_stopped.notify_one(); -} - -void event_capture::stop_capture() { - { - std::scoped_lock init_lock(m_inspector_mutex, m_object_state_mutex); - get_inspector()->stop_capture(); - m_capture_stopped = true; - m_condition_stopped.notify_one(); - } -} - -void event_capture::wait_for_capture_start() { - std::unique_lock lock(m_object_state_mutex); - m_condition_started.wait(lock, [this]() { return m_capture_started; }); -} - -void event_capture::wait_for_capture_stop() { - std::unique_lock lock(m_object_state_mutex); - m_condition_stopped.wait(lock, [this]() { return m_capture_stopped; }); -} - -void event_capture::re_read_dump_file() { - try { - sinsp inspector; - sinsp_evt* event; - - inspector.open_savefile(m_dump_filename); - uint32_t res; - do { - res = inspector.next(&event); - } while(res == SCAP_SUCCESS); - ASSERT_EQ((int)SCAP_EOF, (int)res); - } catch(sinsp_exception& e) { - FAIL() << "caught exception " << e.what(); - } + auto capture_stats_str = capture_stats(m_inspector.get()); + std::cout << capture_stats_str << "\n"; } bool event_capture::handle_event(sinsp_evt* event) { - std::unique_lock object_state_lock(m_object_state_mutex); + bool res = true; + if(::testing::Test::HasNonfatalFailure()) { - return true; + return res; } - bool res = true; + if(m_filter(event)) { try { m_param.m_evt = event; @@ -234,58 +161,88 @@ bool event_capture::handle_event(sinsp_evt* event) { res = false; } } - if(!m_capture_continue()) { - return false; - } if(!res || ::testing::Test::HasNonfatalFailure()) { - std::cerr << "failed on event " << event->get_num() << std::endl; + std::cerr << "failed on event " << event->get_num() << '\n'; } return res; } +// Returns true if any request has been satisfied +bool event_capture::handle_eventfd_request() { + eventfd_t req; + int ret = eventfd_read(m_eventfd, &req); + if(ret == 0) { + // manage request + switch(req) { + case EVENTFD_SIGNAL_STOP: + m_inspector->stop_capture(); + m_leaving = true; + return true; + default: + break; + } + } + return false; +} + +std::string event_capture::capture_stats(sinsp* inspector) { + scap_stats st; + inspector->get_capture_stats(&st); + + std::stringstream ss; + + ss << "capture stats: dropped=" << st.n_drops << " buf=" << st.n_drops_buffer + << " pf=" << st.n_drops_pf << " bug=" << st.n_drops_bug; + + return ss.str(); +} + void event_capture::open_engine(const std::string& engine_string, libsinsp::events::set events_sc_codes) { if(false) { } #ifdef HAS_ENGINE_KMOD else if(!engine_string.compare(KMOD_ENGINE)) { - get_inspector()->open_kmod(m_buffer_dim); + m_inspector->open_kmod(s_buffer_dim, events_sc_codes); } #endif #ifdef HAS_ENGINE_BPF else if(!engine_string.compare(BPF_ENGINE)) { if(event_capture::get_engine().empty()) { std::cerr << "You must specify the path to the bpf probe if you use the 'bpf' engine" - << std::endl; + << '\n'; exit(EXIT_FAILURE); } - get_inspector()->open_bpf(event_capture::get_engine_path().c_str(), m_buffer_dim); + m_inspector->open_bpf(event_capture::get_engine_path(), s_buffer_dim, events_sc_codes); } #endif #ifdef HAS_ENGINE_MODERN_BPF else if(!engine_string.compare(MODERN_BPF_ENGINE)) { - get_inspector()->open_modern_bpf(m_buffer_dim); + m_inspector->open_modern_bpf(s_buffer_dim, + DEFAULT_CPU_FOR_EACH_BUFFER, + true, + events_sc_codes); } #endif else { - std::cerr << "Unknown engine" << std::endl; + std::cerr << "Unknown engine" << '\n'; exit(EXIT_FAILURE); } } void event_capture::set_engine(const std::string& engine_string, const std::string& engine_path) { - m_engine_string = engine_string; - m_engine_path = engine_path; + s_engine_string = engine_string; + s_engine_path = engine_path; } void event_capture::set_buffer_dim(const unsigned long& dim) { - m_buffer_dim = dim; + s_buffer_dim = dim; } const std::string& event_capture::get_engine() { - return m_engine_string; + return s_engine_string; } const std::string& event_capture::get_engine_path() { - return m_engine_path; + return s_engine_path; } diff --git a/test/libsinsp_e2e/event_capture.h b/test/libsinsp_e2e/event_capture.h index cac9bbe2ed..203ddcad39 100644 --- a/test/libsinsp_e2e/event_capture.h +++ b/test/libsinsp_e2e/event_capture.h @@ -22,7 +22,7 @@ limitations under the License. #include -#include +#include #include #include #include @@ -32,63 +32,13 @@ limitations under the License. #include #include #include +#include +#include -class concurrent_object_handle_state_error : public std::logic_error { - using std::logic_error::logic_error; -}; - -class event_capture; - -/** - * The concurrent_object_handle class encapsulates the task of accessing - * event_capture::m_inspector in a thread-safe way, especially in the - * run_callback_t functions passed to event_capture::run(). - */ -template -class concurrent_object_handle { -public: - friend event_capture; - - /** - * Creates a new, unlocked handle with other's wrapped pointer and underlying mutex. - * @param other - */ - concurrent_object_handle(const concurrent_object_handle& other) noexcept: - m_object_ptr(other.m_object_ptr), - m_object_lock(*other.m_object_lock.mutex(), std::defer_lock) {} - - void lock() { m_object_lock.lock(); } - - T* operator->() { - if(!m_object_lock.owns_lock()) { - throw concurrent_object_handle_state_error( - "Attempt to access wrapped object without obtaining a lock."); - } - return m_object_ptr; - } - - inline T* safe_ptr() { return operator->(); } - - T& operator*() { - if(!m_object_lock.owns_lock()) { - throw concurrent_object_handle_state_error( - "Attempt to access wrapped object without obtaining a lock."); - } - return *m_object_ptr; - } - - T* unsafe_ptr() { return m_object_ptr; } - - void unlock() { m_object_lock.unlock(); } - -private: - concurrent_object_handle(sinsp* object_ptr, std::mutex& object_mutex): - m_object_ptr(object_ptr), - m_object_lock(object_mutex, std::defer_lock) {} - - T* m_object_ptr; - std::unique_lock m_object_lock; -}; +// Just a stupid fake FD value to signal to stop capturing events from driver and exit. +// Note: we don't use it through eventfd because we want to make sure +// that we received all events from the driver, until this very last close(FD_SIGNAL_STOP); +#define EVENTFD_SIGNAL_STOP 1 class callback_param { public: @@ -96,120 +46,139 @@ class callback_param { sinsp* m_inspector; }; -typedef std::function before_open_t; -typedef std::function before_close_t; +// Right before inspector->start_capture() gets called. +// Engine is already opened (thus scap handle is already alive). +typedef std::function before_capture_t; +// Right after inspector->stop_capture() gets called. +// Engine is still opened (thus scap handle is still alive). +typedef std::function after_capture_t; +// Only events matching the filter function are passed to the captured_event_callback_t. typedef std::function event_filter_t; +// On event callback typedef std::function captured_event_callback_t; - -// Returns true/false to indicate whether the capture should continue -// or stop -typedef std::function capture_continue_t; - -typedef std::function inspector)> run_callback_t; +typedef std::function run_callback_t; +typedef std::function run_callback_async_t; class event_capture { public: - void init_inspector(); + event_capture(captured_event_callback_t captured_event_callback, + before_capture_t before_open, + after_capture_t before_close, + event_filter_t filter, + uint32_t max_thread_table_size, + uint64_t thread_timeout_ns, + uint64_t inactive_thread_scan_time_ns); + + void start(bool dump, libsinsp::events::set& sc_set); + void stop(); void capture(); - void stop_capture(); - void wait_for_capture_start(); - void wait_for_capture_stop(); static void do_nothing(sinsp* inspector) {} - static bool always_continue() { return true; } + /*! + \brief Run `run_function` synchronously, and + then loop on all events calling filter on them, + and, for any event that matches the filter, + calls captured_event_callback. + Before starting the capture, before_open is called. + After closing the capture, before_close is called. + The default ppm_sc_set is the whole set minus `read` and `readv`. + */ + static void run(const run_callback_t& run_function, + captured_event_callback_t captured_event_callback, + event_filter_t filter, + before_capture_t before_open = event_capture::do_nothing, + after_capture_t before_close = event_capture::do_nothing, + libsinsp::events::set sc_set = {}, + uint32_t max_thread_table_size = 131072, + uint64_t thread_timeout_ns = (uint64_t)60 * 1000 * 1000 * 1000, + uint64_t inactive_thread_scan_time_ns = (uint64_t)60 * 1000 * 1000 * 1000, + bool dump = true) { + event_capture capturing(std::move(captured_event_callback), + std::move(before_open), + std::move(before_close), + std::move(filter), + max_thread_table_size, + thread_timeout_ns, + inactive_thread_scan_time_ns); + + capturing.start(dump, sc_set); + + run_function(capturing.m_inspector.get()); + // signal main thread to end the capture + eventfd_write(capturing.m_eventfd, EVENTFD_SIGNAL_STOP); - sinsp* get_inspector() { - static sinsp inspector = sinsp(); - return &inspector; + capturing.capture(); + + capturing.stop(); } - static void run(run_callback_t run_function, + /*! + \brief Run `run_function` **asynchronously**, while + looping on all events calling filter on them, + and, for any event that matches the filter, + calls captured_event_callback. + Before starting the capture, before_open is called. + After closing the capture, before_close is called. + The default ppm_sc_set is the whole set minus `read` and `readv`. + */ + static void run(const run_callback_async_t& run_function, captured_event_callback_t captured_event_callback, event_filter_t filter, - before_open_t before_open = event_capture::do_nothing, - before_close_t before_close = event_capture::do_nothing, - capture_continue_t capture_continue = event_capture::always_continue, + before_capture_t before_open = event_capture::do_nothing, + after_capture_t before_close = event_capture::do_nothing, + libsinsp::events::set sc_set = {}, uint32_t max_thread_table_size = 131072, uint64_t thread_timeout_ns = (uint64_t)60 * 1000 * 1000 * 1000, uint64_t inactive_thread_scan_time_ns = (uint64_t)60 * 1000 * 1000 * 1000, - sinsp_mode_t mode = SINSP_MODE_LIVE, - uint64_t max_timeouts = 3, bool dump = true) { - event_capture capturing; - { // Synchronized section - std::unique_lock object_state_lock(capturing.m_object_state_mutex); - capturing.m_mode = mode; - capturing.m_captured_event_callback = captured_event_callback; - capturing.m_before_open = before_open; - capturing.m_before_close = before_close; - capturing.m_capture_continue = capture_continue; - capturing.m_filter = filter; - capturing.m_max_thread_table_size = max_thread_table_size; - capturing.m_thread_timeout_ns = thread_timeout_ns; - capturing.m_inactive_thread_scan_time_ns = inactive_thread_scan_time_ns; - capturing.m_max_timeouts = max_timeouts; - capturing.m_dump = dump; - } - - std::thread thread([&capturing]() { capturing.capture(); }); - - capturing.wait_for_capture_start(); - - if(!capturing.m_start_failed.load()) { - run_function(capturing.get_inspector_handle()); - capturing.stop_capture(); - capturing.wait_for_capture_stop(); - } else { - std::unique_lock error_lookup_lock(capturing.m_object_state_mutex); - GTEST_MESSAGE_(capturing.m_start_failure_message.c_str(), - ::testing::TestPartResult::kFatalFailure); - } - + event_capture capturing(std::move(captured_event_callback), + std::move(before_open), + std::move(before_close), + std::move(filter), + max_thread_table_size, + thread_timeout_ns, + inactive_thread_scan_time_ns); + + capturing.start(dump, sc_set); + + std::thread thread([&run_function, &capturing]() { + run_function(); + // signal main thread to end the capture + eventfd_write(capturing.m_eventfd, EVENTFD_SIGNAL_STOP); + }); + + capturing.capture(); thread.join(); + + capturing.stop(); } static void set_engine(const std::string& engine_string, const std::string& engine_path); static const std::string& get_engine(); static void set_buffer_dim(const unsigned long& dim); static const std::string& get_engine_path(); - static std::string m_engine_string; - static std::string m_engine_path; - static unsigned long m_buffer_dim; -private: - event_capture(): m_capture_started(false), m_capture_stopped(false), m_start_failed(false) {} + static std::string capture_stats(sinsp* inspector); - concurrent_object_handle get_inspector_handle(); - - void re_read_dump_file(); + static std::string s_engine_string; + static std::string s_engine_path; + static unsigned long s_buffer_dim; +private: bool handle_event(sinsp_evt* event); + bool handle_eventfd_request(); void open_engine(const std::string& engine_string, libsinsp::events::set events_sc_codes); - std::mutex m_inspector_mutex; // Always lock first - std::mutex m_object_state_mutex; // Always lock second - std::condition_variable m_condition_started; - std::condition_variable m_condition_stopped; - bool m_capture_started; - bool m_capture_stopped; - std::atomic m_start_failed; - + std::unique_ptr m_inspector; + std::unique_ptr m_dumper; event_filter_t m_filter; captured_event_callback_t m_captured_event_callback; - before_open_t m_before_open; - before_close_t m_before_close; - capture_continue_t m_capture_continue; - uint32_t m_max_thread_table_size; - uint64_t m_thread_timeout_ns; - uint64_t m_inactive_thread_scan_time_ns; - std::string m_start_failure_message; - std::string m_dump_filename; - callback_param m_param; - static bool inspector_ok; - sinsp_mode_t m_mode; - uint64_t m_max_timeouts; - bool m_dump; + before_capture_t m_before_capture; + after_capture_t m_after_capture; + callback_param m_param{}; + int m_eventfd; + bool m_leaving; }; diff --git a/test/libsinsp_e2e/forking.cpp b/test/libsinsp_e2e/forking.cpp index 98a01a8154..0035cd676a 100644 --- a/test/libsinsp_e2e/forking.cpp +++ b/test/libsinsp_e2e/forking.cpp @@ -57,7 +57,7 @@ TEST_F(sys_call_test, forking) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { pid_t childtid; int status; childtid = fork(); @@ -110,16 +110,13 @@ TEST_F(sys_call_test, forking_while_scap_stopped) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { int status; // // Stop the capture just before the fork so we lose the event. // - { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->stop_capture(); - } + inspector->stop_capture(); ctid = fork(); @@ -138,13 +135,13 @@ TEST_F(sys_call_test, forking_while_scap_stopped) { // It's a simple way to make sure the capture is started // after the child's clone returned. // - inspector_handle.unsafe_ptr()->start_capture(); + inspector->start_capture(); // // Wait for 5 seconds to make sure the process will still // exist when the sinsp will do the lookup to /proc // - usleep(5000000); + sleep(5); close(fd); _exit(xstatus); // child exits with specific return code } else // fork() returns new pid to the parent process @@ -204,19 +201,25 @@ TEST_F(sys_call_test, forking_while_scap_stopped) { } TEST_F(sys_call_test, forking_process_expired) { - int ptid; // parent tid - int ctid; // child tid + int ptid = gettid(); // parent tid + int ctid = -1; // child tid int status; // // FILTER // - event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_tid() == ptid; }; + event_filter_t filter = [&](sinsp_evt* evt) { + if(evt->get_type() == PPME_SYSCALL_NANOSLEEP_E || + evt->get_type() == PPME_SYSCALL_NANOSLEEP_X) { + return evt->get_tid() == ptid; + } + return false; + }; // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { ctid = fork(); if(ctid >= 0) // fork succeeded @@ -227,17 +230,14 @@ TEST_F(sys_call_test, forking_process_expired) { FAIL(); } else // fork() returns new pid to the parent process { - ptid = getpid(); - // // Wait 10 seconds. During this time, the process should NOT be removed // - struct timespec req, rem; - req.tv_sec = 10; + struct timespec req = {0}; + req.tv_sec = 1; req.tv_nsec = 0; - syscall(__NR_nanosleep, &req, &rem); - + syscall(__NR_nanosleep, &req, nullptr); kill(ctid, SIGUSR1); wait(&status); } @@ -253,15 +253,14 @@ TEST_F(sys_call_test, forking_process_expired) { // captured_event_callback_t callback = [&](const callback_param& param) { sinsp_evt* e = param.m_evt; - - if(e->get_tid() == ptid) { - if(e->get_type() == PPME_SYSCALL_NANOSLEEP_E && !sleep_caught) { + if(!sleep_caught) { + if(e->get_type() == PPME_SYSCALL_NANOSLEEP_E) { // // The child should exist // sinsp_threadinfo* ti = param.m_inspector->get_thread_ref(ctid, false, true).get(); EXPECT_NE((sinsp_threadinfo*)NULL, ti); - } else if(e->get_type() == PPME_SYSCALL_NANOSLEEP_X && !sleep_caught) { + } else if(e->get_type() == PPME_SYSCALL_NANOSLEEP_X) { // // The child should exist // @@ -269,8 +268,6 @@ TEST_F(sys_call_test, forking_process_expired) { EXPECT_NE((sinsp_threadinfo*)NULL, ti); sleep_caught = true; } - } else { - FAIL(); } }; @@ -280,7 +277,7 @@ TEST_F(sys_call_test, forking_process_expired) { filter, event_capture::do_nothing, event_capture::do_nothing, - event_capture::always_continue, + {}, 131072, 5 * ONE_SECOND_IN_NS, ONE_SECOND_IN_NS); @@ -292,7 +289,7 @@ TEST_F(sys_call_test, forking_process_expired) { /////////////////////////////////////////////////////////////////////////////// // CLONE VARIANTS /////////////////////////////////////////////////////////////////////////////// -int ctid; // child tid +std::atomic ctid = -1; // child tid typedef struct { int fd; @@ -314,7 +311,7 @@ static int clone_callback_1(void* arg) { } /* - * The `sys_call_test.forking_clone_fs` e2e test makes the assuption + * The `sys_call_test.forking_clone_fs` e2e test makes the assumption * that, if a children closes a file descriptor, the parent trying * to close the same file descriptor will get an error. This seems * not to be always the case. As the man says `It is probably unwise @@ -328,7 +325,7 @@ TEST_F(sys_call_test, DISABLED_forking_clone_fs) { int callnum = 0; char bcwd[1024]; int prfd; - int ptid; // parent tid + int ptid = gettid(); // parent tid pid_t clone_tid; int child_tid; int parent_res; @@ -346,7 +343,7 @@ TEST_F(sys_call_test, DISABLED_forking_clone_fs) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { const int STACK_SIZE = 65536; /* Stack size for cloned child */ char* stack; /* Start of stack buffer area */ char* stackTop; /* End of stack buffer area */ @@ -354,8 +351,6 @@ TEST_F(sys_call_test, DISABLED_forking_clone_fs) { int status; pid_t pid; - ptid = gettid(); - /* Set up an argument structure to be passed to cloned child, and set some process attributes that will be modified by child */ @@ -397,7 +392,7 @@ TEST_F(sys_call_test, DISABLED_forking_clone_fs) { }; // - // OUTPUT VALDATION + // OUTPUT VALIDATION // captured_event_callback_t callback = [&](const callback_param& param) { sinsp_evt* e = param.m_evt; @@ -467,10 +462,14 @@ TEST_F(sys_call_test, forking_clone_nofs) { int callnum = 0; char bcwd[1024]; int prfd; - int ptid; // parent tid + int ptid = gettid(); // parent tid int flags = CLONE_FS | CLONE_VM; int drflags = PPM_CL_CLONE_FS | PPM_CL_CLONE_VM; + const int STACK_SIZE = 65536; /* Stack size for cloned child */ + char* stack; /* Start of stack buffer area */ + char* stackTop; /* End of stack buffer area */ + // // FILTER // @@ -481,16 +480,11 @@ TEST_F(sys_call_test, forking_clone_nofs) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { - const int STACK_SIZE = 65536; /* Stack size for cloned child */ - char* stack; /* Start of stack buffer area */ - char* stackTop; /* End of stack buffer area */ - clone_params cp; /* Passed to child function */ + run_callback_t test = [&](sinsp* inspector) { + clone_params cp; /* Passed to child function */ int status; pid_t pid; - ptid = getpid(); - /* Set up an argument structure to be passed to cloned child, and set some process attributes that will be modified by child */ @@ -525,13 +519,10 @@ TEST_F(sys_call_test, forking_clone_nofs) { FAIL(); close(cp.fd); - - sleep(1); - free(stack); }; // - // OUTPUT VALDATION + // OUTPUT VALIDATION // captured_event_callback_t callback = [&](const callback_param& param) { sinsp_evt* e = param.m_evt; @@ -586,7 +577,11 @@ TEST_F(sys_call_test, forking_clone_nofs) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + after_capture_t cleanup = [&](sinsp* inspector) { free(stack); }; + + ASSERT_NO_FATAL_FAILURE( + { event_capture::run(test, callback, filter, event_capture::do_nothing, cleanup); }); + EXPECT_EQ(callnum, 4); } @@ -605,11 +600,15 @@ TEST_F(sys_call_test, forking_clone_cwd) { int callnum = 0; char oriwd[1024]; char bcwd[256]; - int ptid; // parent tid + int ptid = gettid(); // parent tid int flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD; int drflags = PPM_CL_CLONE_VM | PPM_CL_CLONE_FS | PPM_CL_CLONE_FILES | PPM_CL_CLONE_SIGHAND | PPM_CL_CLONE_THREAD; + const int STACK_SIZE = 65536; /* Stack size for cloned child */ + char* stack; /* Start of stack buffer area */ + char* stackTop; /* End of stack buffer area */ + // // FILTER // @@ -618,14 +617,7 @@ TEST_F(sys_call_test, forking_clone_cwd) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { - const int STACK_SIZE = 65536; /* Stack size for cloned child */ - char* stack; /* Start of stack buffer area */ - char* stackTop; /* End of stack buffer area */ - clone_params cp; /* Passed to child function */ - - ptid = getpid(); - + run_callback_t test = [&](sinsp* inspector) { ASSERT_TRUE(getcwd(oriwd, 1024) != NULL); /* Allocate stack for child */ @@ -637,22 +629,21 @@ TEST_F(sys_call_test, forking_clone_cwd) { /* Create child; child commences execution in childFunc() */ - if(clone(clone_callback_2, stackTop, flags, &cp) == -1) { + if(clone(clone_callback_2, stackTop, flags, nullptr) == -1) { FAIL(); } + // Give new thread enough time to exit sleep(1); + // The cloned child called chdir("/"); we expect to retrieve "/" here. std::string tmps = getcwd(bcwd, 256); ASSERT_TRUE(chdir(oriwd) == 0); - - sleep(1); - free(stack); }; // - // OUTPUT VALDATION + // OUTPUT VALIDATION // captured_event_callback_t callback = [&](const callback_param& param) { sinsp_evt* e = param.m_evt; @@ -678,9 +669,15 @@ TEST_F(sys_call_test, forking_clone_cwd) { if(ti->m_tid == ptid) { if(callnum > 1) { + // last getcwd call in the test EXPECT_EQ(bcwd, ti->get_cwd()); + EXPECT_EQ(bcwd, std::string("/")); + } else { + // first getcwd call in the test + EXPECT_EQ(std::string(oriwd) + "/", ti->get_cwd()); } } else if(ti->m_tid == ctid) { + // getcwd call by the child EXPECT_EQ("/", ti->get_cwd()); } @@ -688,7 +685,10 @@ TEST_F(sys_call_test, forking_clone_cwd) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + after_capture_t cleanup = [&](sinsp* inspector) { free(stack); }; + + ASSERT_NO_FATAL_FAILURE( + { event_capture::run(test, callback, filter, event_capture::do_nothing, cleanup); }); EXPECT_EQ(3, callnum); } @@ -696,7 +696,7 @@ TEST_F(sys_call_test, forking_clone_cwd) { TEST_F(sys_call_test, forking_main_thread_exit) { int evtnum = 0; int callnum = 0; - int fd; + int64_t fd; pid_t cpid; // parent tid event_filter_t filter = [&](sinsp_evt* evt) { @@ -708,7 +708,7 @@ TEST_F(sys_call_test, forking_main_thread_exit) { } }; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { int status; // ptid = getpid(); @@ -734,13 +734,13 @@ TEST_F(sys_call_test, forking_main_thread_exit) { if(param.m_evt->get_type() == PPME_SYSCALL_OPEN_X) { if(param.m_evt->get_param_value_str("name") == "/etc/passwd") { EXPECT_EQ("/etc/passwd", param.m_evt->get_param_value_str("fd")); - fd = *(int64_t*)param.m_evt->get_param(0)->m_val; + fd = param.m_evt->get_param(0)->as(); ++callnum; } } else if(param.m_evt->get_type() == PPME_SYSCALL_OPENAT_2_X) { if(param.m_evt->get_param_value_str("name") == "/etc/passwd") { EXPECT_EQ("/etc/passwd", param.m_evt->get_param_value_str("fd")); - memcpy(&fd, (int64_t*)param.m_evt->get_param(0)->m_val, sizeof(fd)); + fd = param.m_evt->get_param(0)->as(); ++callnum; } } else if(param.m_evt->get_type() == PPME_PROCEXIT_1_E && param.m_evt->get_tid() == cpid) { @@ -753,7 +753,14 @@ TEST_F(sys_call_test, forking_main_thread_exit) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::all_sc_set()); + }); EXPECT_EQ(3, callnum); } @@ -776,18 +783,10 @@ TEST_F(sys_call_test, forking_main_thread_exit) { // Create the initial stale process. It chdir()s to "/dev", stops the // inspector, and returns. static int stop_sinsp_and_exit(void* arg) { - // Get our own, unlocked concurrent inspector handle - concurrent_object_handle inspector_handle = *(concurrent_object_handle*)arg; - if(chdir("/dev") != 0) { return 1; } - { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->stop_capture(); - } - // Wait 5 seconds. This ensures that the state for this // process will be considered stale when the second process // with the same pid runs. @@ -878,9 +877,9 @@ static pid_t clone_helper(int (*func)(void*), } TEST_F(sys_call_test, remove_stale_thread_clone_exit) { - std::atomic clones_seen(0); + uint32_t clones_seen = 0; stale_clone_ctx ctx; - std::atomic recycle_pid(0); + pid_t recycle_pid; const char* last_pid_filename = "/proc/sys/kernel/ns_last_pid"; struct stat info; @@ -903,11 +902,10 @@ TEST_F(sys_call_test, remove_stale_thread_clone_exit) { // uses the recycled pid. event_filter_t filter = [&](sinsp_evt* evt) { sinsp_threadinfo* tinfo = evt->get_thread_info(); - pid_t rp = recycle_pid.load(); - return (rp != 0 && tinfo && tinfo->m_tid == rp); + return (tinfo && tinfo->m_tid == recycle_pid); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { pid_t launcher_pid; char* launcher_stack = NULL; @@ -921,18 +919,17 @@ TEST_F(sys_call_test, remove_stale_thread_clone_exit) { // This is asynchronous so wait to make sure the thread has started. sleep(1); - // Start a thread that runs and stops the inspector_handle right - // before exiting. This gives us a pid we can use for the - // second thread. - recycle_pid.store(clone_helper(stop_sinsp_and_exit, &inspector_handle)); - ASSERT_GE(recycle_pid.load(), 0); + // Start a thread that runs, chdir to /dev/ and the exits. + // This gives us a pid we can use for the second thread. + // We don't want to capture events from this CLONE. + inspector->stop_capture(); - // The first thread has started, turned off the capturing, and + recycle_pid = clone_helper(stop_sinsp_and_exit, inspector); + ASSERT_GE(recycle_pid, 0); + + // The first thread has started, chdir to /dev, and // exited, so start capturing again. - { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->start_capture(); - } + inspector->start_capture(); // Arrange that the next thread/process created has // pid ctx.m_desired pid by writing to @@ -955,7 +952,7 @@ TEST_F(sys_call_test, remove_stale_thread_clone_exit) { ASSERT_EQ(flock(fileno(last_pid_file), LOCK_EX), 0); - ASSERT_GT(fprintf(last_pid_file, "%d", recycle_pid.load() - 1), 0); + ASSERT_GT(fprintf(last_pid_file, "%d", recycle_pid - 1), 0); fclose(last_pid_file); @@ -1009,5 +1006,5 @@ TEST_F(sys_call_test, remove_stale_thread_clone_exit) { // We must have seen one clone related to the recycled // pid. Otherwise it never actually checked the cwd at all. - EXPECT_EQ(clones_seen.load(), 1u); + EXPECT_EQ(clones_seen, 1u); } diff --git a/test/libsinsp_e2e/fs.cpp b/test/libsinsp_e2e/fs.cpp index 647f548034..a39211e596 100644 --- a/test/libsinsp_e2e/fs.cpp +++ b/test/libsinsp_e2e/fs.cpp @@ -69,7 +69,7 @@ TEST_F(sys_call_test, fs_creat_ulink) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { int fd = creat(FILENAME, 0644); if(fd < 0) { @@ -158,7 +158,7 @@ TEST_F(sys_call_test, fs_mkdir_rmdir) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { mkdir(UNEXISTENT_DIRNAME, 0); if(mkdir(DIRNAME, 0) != 0) { @@ -262,7 +262,7 @@ TEST_F(sys_call_test, fs_openat) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { dirfd = open(".", O_DIRECTORY); if(dirfd <= 0) { FAIL(); @@ -341,7 +341,7 @@ TEST_F(sys_call_test, fs_pread) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { fd = creat(FILENAME, S_IRWXU); if(fd < 0) { FAIL(); @@ -467,7 +467,7 @@ TEST_F(sys_call_test, fs_readv) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { int wv_count; char msg1[10] = "aaaaa"; char msg2[10] = "bbbbb"; @@ -538,7 +538,14 @@ TEST_F(sys_call_test, fs_readv) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::all_sc_set()); + }); EXPECT_EQ(4, callnum); } @@ -561,7 +568,7 @@ TEST_F(sys_call_test, fs_preadv) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { int wv_count; char msg1[10] = "aaaaa"; char msg2[10] = "bbbbb"; @@ -698,7 +705,7 @@ TEST_F(sys_call_test, fs_dup) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { fd = open(FILENAME, O_CREAT | O_WRONLY, 0); fd1 = dup(fd); fd2 = dup2(fd, 333); @@ -823,7 +830,7 @@ TEST_F(sys_call_test, fs_fcntl) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { fd = open(FILENAME, O_CREAT | O_WRONLY, 0); fd1 = fcntl(fd, F_DUPFD, 0); fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 0); @@ -897,7 +904,7 @@ TEST_F(sys_call_test, fs_sendfile) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { struct stat stat_buf; read_fd = open("/etc/passwd", O_RDONLY); @@ -955,7 +962,7 @@ TEST_F(sys_call_test, fs_sendfile_nulloff) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { struct stat stat_buf; read_fd = open("/etc/passwd", O_RDONLY); @@ -1011,7 +1018,7 @@ TEST_F(sys_call_test, fs_sendfile_failed) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { int res = sendfile(-1, -2, NULL, 444); EXPECT_GT(0, res); }; @@ -1060,7 +1067,7 @@ TEST_F(sys_call_test, fs_sendfile_invalidoff) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { struct stat stat_buf; read_fd = open("/etc/passwd", O_RDONLY); @@ -1120,7 +1127,7 @@ TEST_F(sys_call_test, fs_sendfile64) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { struct stat stat_buf; read_fd = open("/etc/passwd", O_RDONLY); @@ -1174,11 +1181,11 @@ TEST_F(sys_call_test, large_read_write) { srandom(42); - before_open_t setup = [&](sinsp* inspector) { inspector->set_snaplen(SNAPLEN_MAX); }; + before_capture_t setup = [&](sinsp* inspector) { inspector->set_snaplen(SNAPLEN_MAX); }; event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { fd1 = creat(FILENAME, S_IRWXU); if(fd1 < 0) { FAIL(); @@ -1236,21 +1243,17 @@ TEST_F(sys_call_test, large_read_write) { } }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->set_snaplen(DEFAULT_SNAPLEN); }; - // We don't dump events to scap files, otherwise we could stuck with modern bpf. ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, - cleanup, - event_capture::always_continue, + event_capture::do_nothing, + libsinsp::events::all_sc_set(), 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, - SINSP_MODE_LIVE, - 3, false); }); @@ -1271,11 +1274,11 @@ TEST_F(sys_call_test, large_readv_writev) { buf[j] = random(); } - before_open_t setup = [&](sinsp* inspector) { inspector->set_snaplen(SNAPLEN_MAX); }; + before_capture_t setup = [&](sinsp* inspector) { inspector->set_snaplen(SNAPLEN_MAX); }; event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { fd = creat(FILENAME, S_IRWXU); if(fd < 0) { FAIL(); @@ -1324,7 +1327,7 @@ TEST_F(sys_call_test, large_readv_writev) { } else if(type == PPME_SYSCALL_WRITEV_X) { if(callnum == 1) { const sinsp_evt_param* p = e->get_param_by_name("data"); - if(event_capture::m_engine_string == KMOD_ENGINE) { + if(event_capture::s_engine_string == KMOD_ENGINE) { // // The driver doesn't have the correct behavior for accumulating // readv/writev, and it uses a single page as a temporary storage area @@ -1346,7 +1349,7 @@ TEST_F(sys_call_test, large_readv_writev) { } else if(type == PPME_SYSCALL_READV_X) { if(callnum == 3) { const sinsp_evt_param* p = e->get_param_by_name("data"); - if(event_capture::m_engine_string == KMOD_ENGINE) { + if(event_capture::s_engine_string == KMOD_ENGINE) { EXPECT_EQ(p->m_len, max_kmod_buf); EXPECT_EQ(0, memcmp(buf, p->m_val, max_kmod_buf)); } else { @@ -1359,21 +1362,17 @@ TEST_F(sys_call_test, large_readv_writev) { } }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->set_snaplen(DEFAULT_SNAPLEN); }; - // We don't dump events to scap files, otherwise we could stuck with modern bpf. ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, - cleanup, - event_capture::always_continue, + event_capture::do_nothing, + libsinsp::events::all_sc_set(), 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, - SINSP_MODE_LIVE, - 3, false); }); @@ -1394,7 +1393,7 @@ TEST_F(sys_call_test, large_open) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { #ifdef SYS_open int fd = syscall(SYS_open, buf.c_str(), O_RDONLY); #else @@ -1412,13 +1411,13 @@ TEST_F(sys_call_test, large_open) { } else if(name.find("open") != std::string::npos && e->get_direction() == SCAP_ED_OUT) { const sinsp_evt_param* p = e->get_param_by_name("name"); - if(event_capture::m_engine_string == KMOD_ENGINE) { + if(event_capture::s_engine_string == KMOD_ENGINE) { EXPECT_EQ(p->m_len, PPM_MAX_ARG_SIZE); EXPECT_EQ(buf.substr(0, PPM_MAX_ARG_SIZE - 1), std::string(p->m_val)); - } else if(event_capture::m_engine_string == BPF_ENGINE) { + } else if(event_capture::s_engine_string == BPF_ENGINE) { EXPECT_EQ(p->m_len, SNAPLEN_MAX); EXPECT_EQ(buf.substr(0, SNAPLEN_MAX - 1), std::string(p->m_val)); - } else if(event_capture::m_engine_string == MODERN_BPF_ENGINE) { + } else if(event_capture::s_engine_string == MODERN_BPF_ENGINE) { EXPECT_EQ(p->m_len, PATH_MAX); EXPECT_EQ(buf.substr(0, PATH_MAX - 1), std::string(p->m_val)); } diff --git a/test/libsinsp_e2e/paths.cpp b/test/libsinsp_e2e/paths.cpp index 881da21789..c681b869ac 100644 --- a/test/libsinsp_e2e/paths.cpp +++ b/test/libsinsp_e2e/paths.cpp @@ -125,14 +125,15 @@ void testdir(string filename, string chdirtarget = "") { // // FILTER // - int tid = getpid(); + int tid = -1; event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_tid() == tid; }; // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { - if(chdirtarget != "") { + run_callback_t test = [&](sinsp* inspector) { + tid = gettid(); + if(!chdirtarget.empty()) { char tcwd[1024]; ASSERT_TRUE(chdir(chdirtarget.c_str()) == 0); @@ -156,7 +157,7 @@ void testdir(string filename, string chdirtarget = "") { unlink(vldt.m_filename.c_str()); - if(chdirtarget != "") { + if(!chdirtarget.empty()) { ASSERT_TRUE(chdir(bcwd) == 0); } }; @@ -421,7 +422,7 @@ TEST_F(sys_call_test, dir_getcwd) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { ASSERT_TRUE(chdir(dir0) == 0); ASSERT_TRUE(getcwd(cwd0, 256) != NULL); @@ -540,7 +541,7 @@ TEST_F(sys_call_test, dir_fchdir) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { int fd; fd = open(dir0, O_RDONLY); diff --git a/test/libsinsp_e2e/process.cpp b/test/libsinsp_e2e/process.cpp index ad556bd587..7991669f41 100644 --- a/test/libsinsp_e2e/process.cpp +++ b/test/libsinsp_e2e/process.cpp @@ -52,8 +52,8 @@ limitations under the License. TEST_F(sys_call_test, process_signalfd_kill) { int callnum = 0; - int ptid; // parent tid - int ctid; // child tid + int ptid = -1; // parent tid + int ctid = -1; // child tid int gptid; // grandparent tid int xstatus = 33; // child exit value int ssfd; @@ -68,7 +68,7 @@ TEST_F(sys_call_test, process_signalfd_kill) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { int status; int sfd; ctid = fork(); @@ -136,7 +136,7 @@ TEST_F(sys_call_test, process_signalfd_kill) { // // PARENT PROCESS // - ptid = getpid(); + ptid = gettid(); gptid = getppid(); // @@ -202,7 +202,14 @@ TEST_F(sys_call_test, process_signalfd_kill) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::all_sc_set()); + }); EXPECT_EQ(7, callnum); } @@ -219,7 +226,7 @@ TEST_F(sys_call_test, DISABLED_process_usleep) { // // TEST CODE // - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = [](sinsp* inspector) { struct timespec req; req.tv_sec = 0; req.tv_nsec = 123456; @@ -271,7 +278,7 @@ TEST_F(sys_call_test, process_inotify) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { int length; int wd; char buffer[EVENT_BUF_LEN]; @@ -288,9 +295,9 @@ TEST_F(sys_call_test, process_inotify) { // // The IN_MODIFY flag causes a notification when a file is written, which should - // heppen immediately in captures + // happen immediately under /proc/ // - wd = inotify_add_watch(fd, LIBSINSP_TEST_CAPTURES_PATH, IN_MODIFY | IN_CREATE | IN_OPEN); + wd = inotify_add_watch(fd, "/proc/", IN_MODIFY | IN_CREATE | IN_OPEN); // // read to determine the event changes @@ -336,7 +343,14 @@ TEST_F(sys_call_test, process_inotify) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::all_sc_set()); + }); EXPECT_EQ(3, callnum); } @@ -378,7 +392,7 @@ TEST(procinfo, process_not_existent) { TEST_F(sys_call_test, process_rlimit) { int callnum = 0; - + struct rlimit curr_rl; // // FILTER // @@ -387,21 +401,20 @@ TEST_F(sys_call_test, process_rlimit) { // // TEST CODE // - run_callback_t test = [](concurrent_object_handle inspector_handle) { - struct rlimit rl; - sleep(1); - + run_callback_t test = [&](sinsp* inspector) { // Called directly because libc likes prlimit() syscall(SYS_getrlimit, RLIMIT_NOFILE, (struct rlimit*)33); - syscall(SYS_getrlimit, RLIMIT_NOFILE, &rl); - rl.rlim_cur = 500; - rl.rlim_max = 1000; - syscall(SYS_setrlimit, RLIMIT_NOFILE, &rl); - syscall(SYS_getrlimit, RLIMIT_NOFILE, &rl); + syscall(SYS_getrlimit, RLIMIT_NOFILE, &curr_rl); + + struct rlimit new_rl; + new_rl.rlim_cur = 5000; + new_rl.rlim_max = 10000; + syscall(SYS_setrlimit, RLIMIT_NOFILE, &new_rl); + syscall(SYS_getrlimit, RLIMIT_NOFILE, &new_rl); }; // - // OUTPUT VALDATION + // OUTPUT VALIDATION // captured_event_callback_t callback = [&](const callback_param& param) { sinsp_evt* e = param.m_evt; @@ -419,8 +432,8 @@ TEST_F(sys_call_test, process_rlimit) { EXPECT_EQ((int64_t)0, std::stoll(e->get_param_value_str("res", false))); if(callnum == 7) { - EXPECT_EQ((int64_t)500, std::stoll(e->get_param_value_str("cur", false))); - EXPECT_EQ((int64_t)1000, std::stoll(e->get_param_value_str("max", false))); + EXPECT_EQ((int64_t)5000, std::stoll(e->get_param_value_str("cur", false))); + EXPECT_EQ((int64_t)10000, std::stoll(e->get_param_value_str("max", false))); } } @@ -435,8 +448,8 @@ TEST_F(sys_call_test, process_rlimit) { EXPECT_EQ((int64_t)0, std::stoll(e->get_param_value_str("res", false))); if(callnum == 5) { - EXPECT_EQ((int64_t)500, std::stoll(e->get_param_value_str("cur", false))); - EXPECT_EQ((int64_t)1000, std::stoll(e->get_param_value_str("max", false))); + EXPECT_EQ((int64_t)5000, std::stoll(e->get_param_value_str("cur", false))); + EXPECT_EQ((int64_t)10000, std::stoll(e->get_param_value_str("max", false))); } callnum++; @@ -463,8 +476,8 @@ TEST_F(sys_call_test, process_rlimit) { break; case 5: EXPECT_EQ(0, res); - EXPECT_EQ(500, newcur); - EXPECT_EQ(1000, newmax); + EXPECT_EQ(5000, newcur); + EXPECT_EQ(10000, newmax); EXPECT_EQ(-1, oldcur); EXPECT_EQ(-1, oldmax); break; @@ -472,14 +485,18 @@ TEST_F(sys_call_test, process_rlimit) { EXPECT_EQ(0, res); EXPECT_EQ(-1, newcur); EXPECT_EQ(-1, newmax); - EXPECT_EQ(500, oldcur); - EXPECT_EQ(1000, oldmax); + EXPECT_EQ(5000, oldcur); + EXPECT_EQ(10000, oldmax); break; } callnum++; } }; + after_capture_t cleanup = [&](sinsp* inspector) { + syscall(SYS_setrlimit, RLIMIT_NOFILE, &curr_rl); + }; + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); EXPECT_EQ(8, callnum); @@ -487,7 +504,6 @@ TEST_F(sys_call_test, process_rlimit) { TEST_F(sys_call_test, process_prlimit) { int callnum = 0; - struct rlimit tmprl; struct rlimit orirl; // @@ -498,13 +514,13 @@ TEST_F(sys_call_test, process_prlimit) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { struct rlimit newrl; struct rlimit oldrl; syscall(SYS_prlimit64, getpid(), RLIMIT_NOFILE, NULL, &orirl); - newrl.rlim_cur = 500; - newrl.rlim_max = 1000; + newrl.rlim_cur = 5000; + newrl.rlim_max = 10000; syscall(SYS_prlimit64, getpid(), RLIMIT_NOFILE, &newrl, &oldrl); syscall(SYS_prlimit64, getpid(), RLIMIT_NOFILE, NULL, &oldrl); }; @@ -532,8 +548,8 @@ TEST_F(sys_call_test, process_prlimit) { EXPECT_EQ((int64_t)orirl.rlim_max, std::stoll(e->get_param_value_str("oldmax", false))); } else if(callnum == 3) { - EXPECT_EQ((int64_t)500, std::stoll(e->get_param_value_str("newcur", false))); - EXPECT_EQ((int64_t)1000, std::stoll(e->get_param_value_str("newmax", false))); + EXPECT_EQ((int64_t)5000, std::stoll(e->get_param_value_str("newcur", false))); + EXPECT_EQ((int64_t)10000, std::stoll(e->get_param_value_str("newmax", false))); EXPECT_EQ((int64_t)orirl.rlim_cur, std::stoll(e->get_param_value_str("oldcur", false))); EXPECT_EQ((int64_t)orirl.rlim_max, @@ -541,19 +557,20 @@ TEST_F(sys_call_test, process_prlimit) { } else if(callnum == 5) { EXPECT_EQ((int64_t)0, std::stoll(e->get_param_value_str("newcur", false))); EXPECT_EQ((int64_t)0, std::stoll(e->get_param_value_str("newmax", false))); - EXPECT_EQ((int64_t)500, std::stoll(e->get_param_value_str("oldcur", false))); - EXPECT_EQ((int64_t)1000, std::stoll(e->get_param_value_str("oldmax", false))); + EXPECT_EQ((int64_t)5000, std::stoll(e->get_param_value_str("oldcur", false))); + EXPECT_EQ((int64_t)10000, std::stoll(e->get_param_value_str("oldmax", false))); } callnum++; } }; - if(syscall(SYS_prlimit64, getpid(), RLIMIT_NOFILE, NULL, &tmprl) != 0) { - return; - } + after_capture_t cleanup = [&](sinsp* inspector) { + syscall(SYS_prlimit64, getpid(), RLIMIT_NOFILE, &orirl, NULL); + }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE( + { event_capture::run(test, callback, filter, event_capture::do_nothing, cleanup); }); EXPECT_EQ(6, callnum); } @@ -617,7 +634,7 @@ TEST_F(sys_call_test, process_scap_proc_get) { // // TEST CODE // - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = [](sinsp* inspector) { usleep(1000); int s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); @@ -715,7 +732,7 @@ TEST_F(sys_call_test, procinfo_processchild_cpuload) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { for(uint32_t j = 0; j < 5; j++) { sleep(1); } @@ -737,11 +754,7 @@ TEST_F(sys_call_test, procinfo_processchild_cpuload) { if(tinfo) { if(tinfo->m_tid == ctid) { - uint64_t tcpu; - - const sinsp_evt_param* parinfo = e->get_param(0); - // tcpu = *(uint64_t*)parinfo->m_val; - memcpy(&tcpu, parinfo->m_val, sizeof(uint64_t)); + auto tcpu = e->get_param(0)->as(); uint64_t delta = tcpu - lastcpu; @@ -786,7 +799,7 @@ TEST_F(sys_call_test, procinfo_two_processchilds_cpuload) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { for(uint32_t j = 0; j < 5; j++) { sleep(1); } @@ -810,10 +823,7 @@ TEST_F(sys_call_test, procinfo_two_processchilds_cpuload) { if(tinfo) { if(tinfo->m_tid == ctid) { - uint64_t tcpu; - - const sinsp_evt_param* parinfo = e->get_param(0); - tcpu = *(uint64_t*)parinfo->m_val; + auto tcpu = e->get_param(0)->as(); uint64_t delta = tcpu - lastcpu; @@ -826,10 +836,7 @@ TEST_F(sys_call_test, procinfo_two_processchilds_cpuload) { callnum++; } else if(tinfo->m_tid == ctid1) { - uint64_t tcpu; - - const sinsp_evt_param* parinfo = e->get_param(0); - tcpu = *(uint64_t*)parinfo->m_val; + auto tcpu = e->get_param(0)->as(); uint64_t delta = tcpu - lastcpu1; diff --git a/test/libsinsp_e2e/suppress_events.cpp b/test/libsinsp_e2e/suppress_events.cpp index 0e8c945b0c..243c0c645a 100644 --- a/test/libsinsp_e2e/suppress_events.cpp +++ b/test/libsinsp_e2e/suppress_events.cpp @@ -25,7 +25,6 @@ static void test_helper_quotactl(test_helper_args& hargs) { // the capture has started we let the test_helper process // perform its work. pid_t pid = getpid(); - bool test_helper_done = false; std::string bin = LIBSINSP_TEST_PATH "/test_helper"; if(hargs.spawn_with_bash) { @@ -38,7 +37,7 @@ static void test_helper_quotactl(test_helper_args& hargs) { // Access/modify inspector before opening // - before_open_t before_open = [&](sinsp* inspector) { + before_capture_t before_open = [&](sinsp* inspector) { inspector->clear_suppress_events_comm(); inspector->clear_suppress_events_tid(); @@ -62,10 +61,9 @@ static void test_helper_quotactl(test_helper_args& hargs) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { if(!hargs.suppress_before) { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->suppress_events_comm( + inspector->suppress_events_comm( std::string((hargs.spawn_with_bash ? "test_helper.sh" : "test_helper"))); } @@ -97,8 +95,6 @@ static void test_helper_quotactl(test_helper_args& hargs) { case PPME_SYSCALL_QUOTACTL_X: if(evt->get_tid() != pid) { FAIL() << "Should not have observed any quotactl event"; - } else { - test_helper_done = true; } break; case PPME_PROCEXIT_1_E: @@ -107,9 +103,7 @@ static void test_helper_quotactl(test_helper_args& hargs) { } }; - capture_continue_t should_continue = [&]() { return (!test_helper_done); }; - - before_close_t before_close = [](sinsp* inspector) { + after_capture_t before_close = [](sinsp* inspector) { scap_stats st; inspector->get_capture_stats(&st); @@ -127,12 +121,11 @@ static void test_helper_quotactl(test_helper_args& hargs) { filter, before_open, before_close, - should_continue, + {}, 131072, 6000, 6000, - SINSP_MODE_LIVE, - 1000); + true); }); } @@ -250,33 +243,28 @@ void suppress_types::run_test(std::vector supp_syscalls) { parse_syscall_names(supp_syscalls, m_suppressed_syscalls); parse_suppressed_types(supp_syscalls, &m_suppressed_evttypes); - // - // TEST CODE - // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + before_capture_t before_open = [&](sinsp* inspector) { for(auto sc : m_suppressed_syscalls) { bool expect_exception = (sc >= PPM_SC_MAX); bool caught_exception = false; try { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->mark_ppm_sc_of_interest(sc, false); + inspector->mark_ppm_sc_of_interest(sc, false); } catch(sinsp_exception& e) { caught_exception = true; } ASSERT_EQ(expect_exception, caught_exception); } + }; - do_syscalls(); - + after_capture_t before_close = [&](sinsp* inspector) { for(auto sc : m_suppressed_syscalls) { bool expect_exception = (sc >= PPM_SC_MAX); bool caught_exception = false; try { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->mark_ppm_sc_of_interest(sc, true); + inspector->mark_ppm_sc_of_interest(sc, true); } catch(sinsp_exception& e) { caught_exception = true; } @@ -285,6 +273,11 @@ void suppress_types::run_test(std::vector supp_syscalls) { } }; + // + // TEST CODE + // + run_callback_t test = [&](sinsp* inspector) { do_syscalls(); }; + // // OUTPUT VALDATION // @@ -296,7 +289,8 @@ void suppress_types::run_test(std::vector supp_syscalls) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, m_tid_filter); }); + ASSERT_NO_FATAL_FAILURE( + { event_capture::run(test, callback, m_tid_filter, before_open, before_close); }); EXPECT_EQ(m_expected_calls, callnum); } diff --git a/test/libsinsp_e2e/sys_call_test.cpp b/test/libsinsp_e2e/sys_call_test.cpp index f2361311f5..558668c039 100644 --- a/test/libsinsp_e2e/sys_call_test.cpp +++ b/test/libsinsp_e2e/sys_call_test.cpp @@ -95,7 +95,7 @@ TEST_F(sys_call_test, stat) { return evt_name.find("stat") != std::string::npos && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = [](sinsp* inspector) { struct stat sb; stat("/tmp", &sb); }; @@ -114,7 +114,7 @@ TEST_F(sys_call_test, open_close) { m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = [](sinsp* inspector) { int fd = open("/tmp", O_RDONLY); close(fd); }; @@ -135,7 +135,7 @@ TEST_F(sys_call_test, open_close) { TEST_F(sys_call_test, open_close_dropping) { int callnum = 0; - before_open_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; + before_capture_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; event_filter_t filter = [&](sinsp_evt* evt) { return (0 == strcmp(evt->get_name(), "open") || 0 == strcmp(evt->get_name(), "openat") || @@ -143,7 +143,7 @@ TEST_F(sys_call_test, open_close_dropping) { m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = [](sinsp* inspector) { int fd = open("/tmp", O_RDONLY); close(fd); }; @@ -157,9 +157,7 @@ TEST_F(sys_call_test, open_close_dropping) { } }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->stop_dropping_mode(); }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); EXPECT_EQ(2, callnum); } @@ -170,9 +168,7 @@ TEST_F(sys_call_test, fcntl_getfd) { return 0 == strcmp(evt->get_name(), "fcntl") && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { - fcntl(0, F_GETFL); - }; + run_callback_t test = [](sinsp* inspector) { fcntl(0, F_GETFL); }; captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; @@ -183,21 +179,17 @@ TEST_F(sys_call_test, fcntl_getfd) { TEST_F(sys_call_test, fcntl_getfd_dropping) { int callnum = 0; - before_open_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; + before_capture_t setup = [](sinsp* inspector) { inspector->start_dropping_mode(1); }; event_filter_t filter = [&](sinsp_evt* evt) { return 0 == strcmp(evt->get_name(), "fcntl") && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { - fcntl(0, F_GETFL); - }; + run_callback_t test = [](sinsp* inspector) { fcntl(0, F_GETFL); }; captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->stop_dropping_mode(); }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); EXPECT_EQ(0, callnum); } @@ -207,9 +199,7 @@ TEST_F(sys_call_test, bind_error) { return 0 == strcmp(evt->get_name(), "bind") && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { - bind(0, NULL, 0); - }; + run_callback_t test = [](sinsp* inspector) { bind(0, NULL, 0); }; captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; @@ -220,21 +210,17 @@ TEST_F(sys_call_test, bind_error) { TEST_F(sys_call_test, bind_error_dropping) { int callnum = 0; - before_open_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; + before_capture_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; event_filter_t filter = [&](sinsp_evt* evt) { return 0 == strcmp(evt->get_name(), "bind") && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { - bind(0, NULL, 0); - }; + run_callback_t test = [](sinsp* inspector) { bind(0, NULL, 0); }; captured_event_callback_t callback = [&](const callback_param& param) { callnum++; }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->stop_dropping_mode(); }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); EXPECT_EQ(1, callnum); } @@ -244,7 +230,7 @@ TEST_F(sys_call_test, close_badfd) { return 0 == strcmp(evt->get_name(), "close") && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = [](sinsp* inspector) { close(-1); close(INT_MAX); }; @@ -265,13 +251,13 @@ TEST_F(sys_call_test, close_badfd) { TEST_F(sys_call_test, close_badfd_dropping) { int callnum = 0; - before_open_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; + before_capture_t setup = [&](sinsp* inspector) { inspector->start_dropping_mode(1); }; event_filter_t filter = [&](sinsp_evt* evt) { return 0 == strcmp(evt->get_name(), "close") && m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = [](sinsp* inspector) { close(-1); close(INT_MAX); }; @@ -285,9 +271,7 @@ TEST_F(sys_call_test, close_badfd_dropping) { } }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->stop_dropping_mode(); }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); EXPECT_EQ(0, callnum); } @@ -305,7 +289,7 @@ TEST_F(sys_call_test, poll_timeout) { std::string my_pipe[2]; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { subprocess handle(LIBSINSP_TEST_PATH "/test_helper", {"poll_timeout"}); std::stringstream ss; ss << handle.out(); @@ -376,7 +360,7 @@ TEST_F(sys_call_test, ioctl) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; int status; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { int fd; fd = open("/dev/ttyS0", O_RDONLY); @@ -413,7 +397,7 @@ TEST_F(sys_call_test, shutdown) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; int sock; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { FAIL() << "socket() failed"; return; @@ -459,7 +443,7 @@ TEST_F(sys_call_test, timerfd) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; int fd; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { int ret; unsigned int ns; unsigned int sec; @@ -512,7 +496,14 @@ TEST_F(sys_call_test, timerfd) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::all_sc_set()); + }); EXPECT_EQ(3, callnum); } @@ -523,9 +514,20 @@ TEST_F(sys_call_test, timestamp) { uint64_t timestampv[20]; int callnum = 0; + before_capture_t setup = [&](sinsp* inspector) { + // Drop all but generic syscalls (since PPM_SC_GETTIMEOFDAY is generic) + // to avoid drops. + const auto state_sc_set = libsinsp::events::sinsp_state_sc_set(); + for(int i = 0; i < PPM_SC_MAX; i++) { + if((ppm_sc_code)i != PPM_SC_GETTIMEOFDAY) { + inspector->mark_ppm_sc_of_interest((ppm_sc_code)i, false); + } + } + }; + event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { useconds_t sleep_period = 10; struct timeval tv; for(uint32_t j = 0; j < sizeof(timestampv) / sizeof(timestampv[0]); ++j) { @@ -545,7 +547,7 @@ TEST_F(sys_call_test, timestamp) { } }; - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); EXPECT_EQ((int)(sizeof(timestampv) / sizeof(timestampv[0])), callnum); } @@ -554,7 +556,7 @@ TEST_F(sys_call_test, brk) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [](concurrent_object_handle inspector_handle) { + run_callback_t test = [](sinsp* inspector) { sbrk(1000); sbrk(100000); }; @@ -616,7 +618,7 @@ TEST_F(sys_call_test, mmap) { void* p; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { munmap((void*)0x50, 300); p = mmap(0, 0, @@ -770,7 +772,7 @@ TEST_F(sys_call_test, quotactl_ko) { evt->get_type() == PPME_SYSCALL_QUOTACTL_E; }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { quotactl(QCMD(Q_QUOTAON, USRQUOTA), "/dev/xxx", 2, @@ -839,7 +841,7 @@ TEST_F(sys_call_test, quotactl_ok) { struct dqblk mydqblk; struct dqinfo mydqinfo; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { quotactl(QCMD(Q_QUOTAON, USRQUOTA), "/dev/loop0", 2, @@ -939,7 +941,7 @@ TEST_F(sys_call_test, getsetuid_and_gid) { event_filter_t filter = [&](sinsp_evt* evt) { return m_tid_filter(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { auto res = setuid(0); EXPECT_EQ(0, res); res = setgid(test_gid); @@ -1024,7 +1026,7 @@ TEST_F(sys_call_test32, execve_ia32_emulation) { int callnum = 0; std::unique_ptr is_subprocess_execve; - before_open_t before_open = [&](sinsp* inspector) { + before_capture_t before_open = [&](sinsp* inspector) { sinsp_filter_compiler compiler(inspector, "evt.type=execve and proc.apid=" + std::to_string(getpid())); is_subprocess_execve = compiler.compile(); @@ -1032,7 +1034,7 @@ TEST_F(sys_call_test32, execve_ia32_emulation) { event_filter_t filter = [&](sinsp_evt* evt) { return is_subprocess_execve->run(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { auto ret = system(LIBSINSP_TEST_RESOURCES_PATH "execve32 " LIBSINSP_TEST_RESOURCES_PATH "execve " LIBSINSP_TEST_RESOURCES_PATH "execve32"); @@ -1093,7 +1095,7 @@ TEST_F(sys_call_test32, quotactl_ko) { evt->get_type() == PPME_SYSCALL_QUOTACTL_E; }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { subprocess handle(LIBSINSP_TEST_PATH "/test_helper_32", {"quotactl_ko"}); handle.wait(); }; @@ -1140,7 +1142,7 @@ TEST_F(sys_call_test, setns_test) { return m_tid_filter(evt) && (evt->get_type() == PPME_SYSCALL_SETNS_E || evt->get_type() == PPME_SYSCALL_SETNS_X); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { fd = open("/proc/self/ns/net", O_RDONLY); ASSERT_NE(0, fd); ASSERT_EQ(0, setns(fd, CLONE_NEWNET)); @@ -1171,7 +1173,7 @@ TEST_F(sys_call_test, unshare_) { (evt->get_type() == PPME_SYSCALL_UNSHARE_E || evt->get_type() == PPME_SYSCALL_UNSHARE_X); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { auto child = fork(); if(child == 0) { unshare(CLONE_NEWUTS); @@ -1203,7 +1205,7 @@ TEST_F(sys_call_test, sendmsg_recvmsg_SCM_RIGHTS) { auto tinfo = evt->get_thread_info(true); return tinfo->get_comm() == "libsinsp_e2e_te" && evt->get_type() == PPME_SOCKET_RECVMSG_X; }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { int server_sd, worker_sd, pair_sd[2]; int rc = socketpair(AF_UNIX, SOCK_DGRAM, 0, pair_sd); ASSERT_GE(rc, 0); @@ -1290,7 +1292,7 @@ TEST_F(sys_call_test, ppoll_timeout) { ti->m_comm == "test_helper"; }; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { subprocess handle(LIBSINSP_TEST_PATH "/test_helper", {"ppoll_timeout"}); handle.wait(); }; @@ -1373,7 +1375,7 @@ TEST_F(sys_call_test, getsetresuid_and_gid) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { char command[] = "useradd -u 5454 testsetresuid && " "groupadd -g 6565 testsetresgid && " @@ -1453,7 +1455,7 @@ TEST_F(sys_call_test, getsetresuid_and_gid) { } }; - before_close_t cleanup = [&](sinsp* inspector) { + after_capture_t before_close = [&](sinsp* inspector) { int result = 0; result += setresuid(orig_uids[0], orig_uids[1], orig_uids[2]); @@ -1464,8 +1466,9 @@ TEST_F(sys_call_test, getsetresuid_and_gid) { } }; - ASSERT_NO_FATAL_FAILURE( - { event_capture::run(test, callback, filter, event_capture::do_nothing, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, callback, filter, event_capture::do_nothing, before_close); + }); EXPECT_EQ(8, callnum); } @@ -1484,7 +1487,7 @@ TEST_F(sys_call_test, failing_execve) { printf("%s %s %s %s %s\n", eargv[0], eargv[1], eargv[2], eargv[3], eargv[4]); printf("%s %s %s %s\n", eenvp[0], eenvp[1], eenvp[2], eenvp[3]); - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { int ret = execve(eargv[0], (char* const*)eargv, (char* const*)eenvp); ASSERT_TRUE(ret < 0); }; @@ -1537,7 +1540,7 @@ TEST_F(sys_call_test, large_execve) { buf.append(std::to_string(random())); } - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { ctid = fork(); if(ctid < 0) { @@ -1623,7 +1626,7 @@ TEST_F(sys_call_test32, failing_execve) { // INIT FILTER std::unique_ptr is_subprocess_execve; - before_open_t before_open = [&](sinsp* inspector) { + before_capture_t before_open = [&](sinsp* inspector) { sinsp_filter_compiler compiler(inspector, "evt.type=execve and proc.apid=" + std::to_string(getpid())); is_subprocess_execve.reset(compiler.compile().release()); @@ -1637,7 +1640,7 @@ TEST_F(sys_call_test32, failing_execve) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { auto ret = system(LIBSINSP_TEST_RESOURCES_PATH "execve32_fail"); ASSERT_TRUE(ret > 0); ret = system(LIBSINSP_TEST_RESOURCES_PATH "execve32 ./fail"); @@ -1727,12 +1730,12 @@ TEST_F(sys_call_test32, mmap) { return tinfo && tinfo->m_comm == "test_helper_32" && ps_filter(evt); }; - uint64_t p = 0; + uint64_t p = -1; // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { subprocess handle(LIBSINSP_TEST_PATH "/test_helper_32", { "mmap_test", @@ -1743,10 +1746,8 @@ TEST_F(sys_call_test32, mmap) { errno2 = std::stoi(tmp.str()); tmp.clear(); tmp.str(""); - tmp << handle.out(); - p = (uint64_t)std::stoul(tmp.str()); - tmp.clear(); - tmp.str(""); + tmp << std::hex << handle.out(); + tmp >> p; handle.wait(); }; @@ -1774,8 +1775,7 @@ TEST_F(sys_call_test32, mmap) { EXPECT_EQ("300", e->get_param_value_str("length")); break; case 7: { - uint64_t addr = 0; - memcpy(&addr, e->get_param_by_name("addr")->m_val, sizeof(uint64_t)); + auto addr = e->get_param_by_name("addr")->as(); #ifdef __LP64__ EXPECT_EQ((uint64_t)p, addr); #else @@ -1790,8 +1790,8 @@ TEST_F(sys_call_test32, mmap) { } else if(type == PPME_SYSCALL_MUNMAP_X) { callnum++; - memcpy(&exit_vmsize, e->get_param_by_name("vm_size")->m_val, sizeof(uint32_t)); - memcpy(&exit_vmrss, e->get_param_by_name("vm_rss")->m_val, sizeof(uint32_t)); + exit_vmsize = e->get_param_by_name("vm_size")->as(); + exit_vmrss = e->get_param_by_name("vm_rss")->as(); EXPECT_EQ(e->get_thread_info(false)->m_vmsize_kb, exit_vmsize); EXPECT_EQ(e->get_thread_info(false)->m_vmrss_kb, exit_vmrss); @@ -1848,22 +1848,20 @@ TEST_F(sys_call_test32, mmap) { } else if(type == PPME_SYSCALL_MMAP_X || type == PPME_SYSCALL_MMAP2_X) { callnum++; - memcpy(&exit_vmsize, e->get_param_by_name("vm_size")->m_val, sizeof(uint32_t)); - memcpy(&exit_vmrss, e->get_param_by_name("vm_rss")->m_val, sizeof(uint32_t)); + exit_vmsize = e->get_param_by_name("vm_size")->as(); + exit_vmrss = e->get_param_by_name("vm_rss")->as(); EXPECT_EQ(e->get_thread_info(false)->m_vmsize_kb, exit_vmsize); EXPECT_EQ(e->get_thread_info(false)->m_vmrss_kb, exit_vmrss); switch(callnum) { case 4: { - uint64_t res = 0; - memcpy(&res, e->get_param_by_name("res")->m_val, sizeof(uint64_t)); - EXPECT_EQ(-errno2, (int64_t)res); + auto res = e->get_param_by_name("res")->as(); + EXPECT_EQ(-errno2, res); break; } case 6: { - uint64_t res = 0; - memcpy(&res, e->get_param_by_name("res")->m_val, sizeof(uint64_t)); - EXPECT_EQ((uint64_t)p, res); + auto res = e->get_param_by_name("res")->as(); + EXPECT_EQ(p, res); EXPECT_GT(exit_vmsize, enter_vmsize + 500); EXPECT_GE(exit_vmrss, enter_vmrss); break; @@ -1889,7 +1887,7 @@ TEST_F(sys_call_test32, ppoll_timeout) { std::string my_pipe[2]; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { subprocess handle(LIBSINSP_TEST_PATH "/test_helper_32", { "ppoll_timeout", @@ -1976,7 +1974,7 @@ TEST_F(sys_call_test32, fs_preadv) { // // TEST CODE // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { subprocess test_proc(LIBSINSP_TEST_PATH "/test_helper_32", {"preadv_pwritev"}); fd = std::stoi(test_proc.out()); int bool_n = std::stoi(test_proc.out()); @@ -2075,38 +2073,33 @@ TEST_F(sys_call_test, thread_lookup_static) { event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_type() != PPME_PROCEXIT_1_E && evt->get_tid() > 0; }; - run_callback_t test = [&](concurrent_object_handle inspector) { return; }; - captured_event_callback_t callback = [&](const callback_param& param) { return; }; - scap_linux_platform* platform; - - before_close_t before_close = [&](sinsp* inspector) { - platform = (scap_linux_platform*)inspector->get_scap_platform(); + run_callback_t test = [&](sinsp* inspector) { return; }; + captured_event_callback_t callback = [&](const callback_param& param) { + auto* platform = (scap_linux_platform*)param.m_inspector->get_scap_platform(); + ASSERT_EQ(SCAP_SUCCESS, + scap_proc_read_thread(platform, proc, 1, &scap_tinfo, err_buf, false)); + + EXPECT_EQ(1, scap_tinfo.tid); + EXPECT_EQ(1, scap_tinfo.pid); + EXPECT_EQ(1, scap_tinfo.vtid); + EXPECT_EQ(0, scap_tinfo.ptid); + + ASSERT_EQ(SCAP_SUCCESS, + scap_proc_read_thread(platform, proc, 62725, &scap_tinfo, err_buf, false)); + EXPECT_EQ(62725, scap_tinfo.tid); + EXPECT_EQ(62725, scap_tinfo.pid); + EXPECT_EQ(62725, scap_tinfo.vtid); + EXPECT_EQ(1, scap_tinfo.ptid); + + ASSERT_EQ(SCAP_SUCCESS, + scap_proc_read_thread(platform, proc, 62727, &scap_tinfo, err_buf, false)); + EXPECT_EQ(62727, scap_tinfo.tid); + EXPECT_EQ(62725, scap_tinfo.pid); + EXPECT_EQ(62727, scap_tinfo.vtid); + EXPECT_EQ(1, scap_tinfo.ptid); }; - ASSERT_NO_FATAL_FAILURE({ - event_capture::run(test, callback, filter, event_capture::do_nothing, before_close); - }); - - ASSERT_EQ(SCAP_SUCCESS, scap_proc_read_thread(platform, proc, 1, &scap_tinfo, err_buf, false)); - - EXPECT_EQ(1, scap_tinfo.tid); - EXPECT_EQ(1, scap_tinfo.pid); - EXPECT_EQ(1, scap_tinfo.vtid); - EXPECT_EQ(0, scap_tinfo.ptid); - - ASSERT_EQ(SCAP_SUCCESS, - scap_proc_read_thread(platform, proc, 62725, &scap_tinfo, err_buf, false)); - EXPECT_EQ(62725, scap_tinfo.tid); - EXPECT_EQ(62725, scap_tinfo.pid); - EXPECT_EQ(62725, scap_tinfo.vtid); - EXPECT_EQ(1, scap_tinfo.ptid); - - ASSERT_EQ(SCAP_SUCCESS, - scap_proc_read_thread(platform, proc, 62727, &scap_tinfo, err_buf, false)); - EXPECT_EQ(62727, scap_tinfo.tid); - EXPECT_EQ(62725, scap_tinfo.pid); - EXPECT_EQ(62727, scap_tinfo.vtid); - EXPECT_EQ(1, scap_tinfo.ptid); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); } TEST_F(sys_call_test, thread_lookup_live) { @@ -2119,7 +2112,7 @@ TEST_F(sys_call_test, thread_lookup_live) { event_filter_t filter = [&](sinsp_evt* evt) { return evt->get_type() != PPME_PROCEXIT_1_E && evt->get_tid() > 0; }; - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { // a very short sleep to gather some events, // we'll take much longer than this to process them all usleep(1000); @@ -2153,29 +2146,29 @@ TEST_F(sys_call_test, thread_lookup_live) { } }; - scap_linux_platform* platform; - - before_close_t before_close = [&](sinsp* inspector) { + after_capture_t before_close = [&](sinsp* inspector) { // close scap to maintain the num_consumers at exit == 0 assertion // close_capture(scap, platform); - platform = (scap_linux_platform*)inspector->get_scap_platform(); + auto platform = (scap_linux_platform*)inspector->get_scap_platform(); + + ASSERT_EQ(SCAP_SUCCESS, + scap_proc_read_thread(platform, proc, getpid(), &scap_tinfo, err_buf, false)); + EXPECT_EQ(getpid(), scap_tinfo.tid); + EXPECT_EQ(getpid(), scap_tinfo.pid); + EXPECT_EQ(getpid(), scap_tinfo.vtid); + EXPECT_EQ(getppid(), scap_tinfo.ptid); + + ASSERT_EQ(SCAP_SUCCESS, + scap_proc_read_thread(platform, proc, 1, &scap_tinfo, err_buf, false)); + EXPECT_EQ(1, scap_tinfo.tid); + EXPECT_EQ(1, scap_tinfo.pid); + EXPECT_EQ(1, scap_tinfo.vtid); + EXPECT_EQ(0, scap_tinfo.ptid); }; + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, event_capture::do_nothing, before_close); }); - - ASSERT_EQ(SCAP_SUCCESS, - scap_proc_read_thread(platform, proc, getpid(), &scap_tinfo, err_buf, false)); - EXPECT_EQ(getpid(), scap_tinfo.tid); - EXPECT_EQ(getpid(), scap_tinfo.pid); - EXPECT_EQ(getpid(), scap_tinfo.vtid); - EXPECT_EQ(getppid(), scap_tinfo.ptid); - - ASSERT_EQ(SCAP_SUCCESS, scap_proc_read_thread(platform, proc, 1, &scap_tinfo, err_buf, false)); - EXPECT_EQ(1, scap_tinfo.tid); - EXPECT_EQ(1, scap_tinfo.pid); - EXPECT_EQ(1, scap_tinfo.vtid); - EXPECT_EQ(0, scap_tinfo.ptid); } TEST_F(sys_call_test, fd_name_max_path) { @@ -2189,9 +2182,7 @@ TEST_F(sys_call_test, fd_name_max_path) { m_tid_filter(evt); }; - run_callback_t test = [&](concurrent_object_handle inspector_handle) { - open(pathname.c_str(), O_RDONLY); - }; + run_callback_t test = [&](sinsp* inspector) { open(pathname.c_str(), O_RDONLY); }; sinsp_filter_check_list m_filterlist; diff --git a/test/libsinsp_e2e/sys_call_test.h b/test/libsinsp_e2e/sys_call_test.h index 1f1036ad68..2248f8b4a3 100644 --- a/test/libsinsp_e2e/sys_call_test.h +++ b/test/libsinsp_e2e/sys_call_test.h @@ -57,17 +57,19 @@ class sys_call_test : public testing::Test { protected: void SetUp() { - m_tid = getpid(); - m_tid_filter = [this](sinsp_evt* evt) { + m_pid = getpid(); + // Check that the event comes from a secondary thread inside the process, + // since the test callback is ran on an helper thread. + m_tid_filter = [&](sinsp_evt* evt) { if(evt->get_param_value_str("fd").find(LIBSINSP_TEST_KERNEL_MODULE_NAME) != std::string::npos) { return false; } - return evt->get_tid() == m_tid; + return evt->get_tid() == m_pid; }; }; - __pid_t m_tid; + __pid_t m_pid; event_filter_t m_tid_filter; }; diff --git a/test/libsinsp_e2e/tcp_client_server.cpp b/test/libsinsp_e2e/tcp_client_server.cpp index c5d9625ca2..23e861849e 100644 --- a/test/libsinsp_e2e/tcp_client_server.cpp +++ b/test/libsinsp_e2e/tcp_client_server.cpp @@ -110,11 +110,9 @@ void runtest(iotype iot, // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { - { - std::scoped_lock inspector_handle_lock(inspector_handle); - inspector_handle->dynamic_snaplen(true); - } + before_capture_t before = [&](sinsp* inspector) { inspector->dynamic_snaplen(true); }; + + run_callback_t test = [&](sinsp* inspector) { server_proc.start(); server_proc.wait_for_start(); server_pid = server_proc.get_pid(); @@ -275,14 +273,12 @@ void runtest(iotype iot, event_capture::run(test, callback, filter, + before, event_capture::do_nothing, - event_capture::do_nothing, - event_capture::always_continue, + libsinsp::events::all_sc_set(), 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, - SINSP_MODE_LIVE, - 3, false); }); ASSERT_GT(callnum, 0); @@ -347,7 +343,7 @@ TEST_F(sys_call_test, tcp_client_server_with_connection_before_capturing_starts) // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { server.signal_continue(); client.signal_continue(); server_thread.join(); @@ -375,12 +371,10 @@ TEST_F(sys_call_test, tcp_client_server_with_connection_before_capturing_starts) filter, event_capture::do_nothing, event_capture::do_nothing, - event_capture::always_continue, + {}, 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, - SINSP_MODE_LIVE, - 3, false); }); ASSERT_EQ(1, state); diff --git a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp index c05561014f..f60d306226 100644 --- a/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp +++ b/test/libsinsp_e2e/tcp_client_server_ipv4_mapped.cpp @@ -374,7 +374,7 @@ void runtest_ipv4m(iotype iot, std::string sport; int state = 0; int ctid; - int tid = getpid(); + int tid = -1; // // FILTER @@ -386,7 +386,8 @@ void runtest_ipv4m(iotype iot, // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_async_t test = [&]() { + tid = gettid(); server_thread = std::thread(&tcp_server_ipv4m::run, server); server->wait_till_ready(); @@ -402,10 +403,6 @@ void runtest_ipv4m(iotype iot, tee(-1, -1, 0, 0); }; - std::function log_param = [](const callback_param& param) { - // std::cerr << param.m_evt->get_name() << std::endl; - }; - // // OUTPUT VALIDATION // @@ -444,15 +441,12 @@ void runtest_ipv4m(iotype iot, if(!exit_no_close) { EXPECT_EQ(SERVER_PORT_STR, dst_port); } - log_param(param); callnum++; } else if(evt->get_type() == PPME_SOCKET_LISTEN_E) { EXPECT_EQ("1", evt->get_param_value_str("backlog")); - log_param(param); callnum++; } else if(evt->get_type() == PPME_SOCKET_LISTEN_X) { EXPECT_EQ("0", evt->get_param_value_str("res")); - log_param(param); callnum++; } else if(evt->get_type() == PPME_SOCKET_ACCEPT4_6_E) { EXPECT_EQ("0", evt->get_param_value_str("flags")); @@ -479,7 +473,6 @@ void runtest_ipv4m(iotype iot, EXPECT_EQ(SERVER_PORT_STR, dst_port); } - log_param(param); callnum++; } @@ -492,9 +485,7 @@ void runtest_ipv4m(iotype iot, // recvfrom() and sets the address to NULL // if(evt->get_type() == PPME_SOCKET_SEND_E || evt->get_type() == PPME_SOCKET_RECV_E || - evt->get_type() == PPME_SOCKET_SENDTO_E || evt->get_type() == PPME_SOCKET_RECVFROM_E || - evt->get_type() == PPME_SYSCALL_READ_E || evt->get_type() == PPME_SYSCALL_WRITE_E || - evt->get_type() == PPME_SYSCALL_READV_E || evt->get_type() == PPME_SYSCALL_WRITEV_E) { + evt->get_type() == PPME_SOCKET_SENDTO_E || evt->get_type() == PPME_SOCKET_RECVFROM_E) { if(evt->get_type() == PPME_SOCKET_RECVFROM_E) { if(evt->get_param_value_str("tuple") != "") { EXPECT_EQ("NULL", evt->get_param_value_str("tuple")); @@ -515,11 +506,9 @@ void runtest_ipv4m(iotype iot, EXPECT_EQ(SERVER_PORT_STR, dst_port); } - log_param(param); callnum++; } else if(evt->get_type() == PPME_SOCKET_RECV_X || - evt->get_type() == PPME_SOCKET_RECVFROM_X || - evt->get_type() == PPME_SYSCALL_READ_X) { + evt->get_type() == PPME_SOCKET_RECVFROM_X) { if(evt->get_type() == PPME_SOCKET_RECVFROM_X) { if(!parse_tuple(evt->get_param_value_str("tuple"), src_addr, @@ -550,14 +539,6 @@ void runtest_ipv4m(iotype iot, EXPECT_EQ(PAYLOAD, evt->get_param_value_str("data")); - log_param(param); - callnum++; - } else if(evt->get_type() == PPME_SYSCALL_READV_X) { - std::string ds = evt->get_param_value_str("data"); - - EXPECT_EQ(ds, evt->get_param_value_str("data")); - - log_param(param); callnum++; } @@ -589,12 +570,10 @@ void runtest_ipv4m(iotype iot, filter, event_capture::do_nothing, event_capture::do_nothing, - event_capture::always_continue, + {}, 131072, (uint64_t)60 * 1000 * 1000 * 1000, (uint64_t)60 * 1000 * 1000 * 1000, - SINSP_MODE_LIVE, - 3, false); }); } @@ -646,7 +625,7 @@ TEST_F(sys_call_test, tcp_client_server_with_connection_before_capturing_starts_ // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector) { + run_callback_t test = [&](sinsp* inspector) { server.signal_continue(); client.signal_continue(); server_thread.join(); @@ -664,8 +643,8 @@ TEST_F(sys_call_test, tcp_client_server_with_connection_before_capturing_starts_ }; server_thread = std::thread(&tcp_server_ipv4m::run, &server); - client_thread = std::thread(&tcp_client_ipv4m::run, &client); server.wait_till_ready(); + client_thread = std::thread(&tcp_client_ipv4m::run, &client); client.wait_till_ready(); ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); diff --git a/test/libsinsp_e2e/test_helper.cpp b/test/libsinsp_e2e/test_helper.cpp index 11764f22c7..d6d35be6c8 100644 --- a/test/libsinsp_e2e/test_helper.cpp +++ b/test/libsinsp_e2e/test_helper.cpp @@ -83,7 +83,7 @@ void mmap_test(const vector& args) { munmap(p, 1003520); printf("%d\n", errno2); fflush(stdout); - printf("%u\n", p); + printf("%p\n", p); fflush(stdout); } diff --git a/test/libsinsp_e2e/udp_client_server.cpp b/test/libsinsp_e2e/udp_client_server.cpp index 77b23247e2..9c57ce0187 100644 --- a/test/libsinsp_e2e/udp_client_server.cpp +++ b/test/libsinsp_e2e/udp_client_server.cpp @@ -469,7 +469,7 @@ TEST_F(sys_call_test, udp_client_server) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { udps.start(); }; + run_callback_t test = [&](sinsp* inspector) { udps.start(); }; // // OUTPUT VALDATION @@ -598,7 +598,7 @@ TEST_F(sys_call_test, udp_client_server_with_connect_by_client) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { udps.start(); }; + run_callback_t test = [&](sinsp* inspector) { udps.start(); }; // // OUTPUT VALDATION @@ -635,7 +635,7 @@ TEST_F(sys_call_test, udp_client_server_sendmsg) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { udps.start(); }; + run_callback_t test = [&](sinsp* inspector) { udps.start(); }; // // OUTPUT VALDATION @@ -691,7 +691,7 @@ TEST_F(sys_call_test, udp_client_server_sendmsg_2buf) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { udps.start(); }; + run_callback_t test = [&](sinsp* inspector) { udps.start(); }; // // OUTPUT VALDATION @@ -747,7 +747,7 @@ static void run_fd_name_changed_test(bool use_sendmsg, uint32_t num_name_changed_evts = 0; // INIT FILTER - before_open_t before_open = [&](sinsp* inspector) { + before_capture_t before_open = [&](sinsp* inspector) { sinsp_filter_compiler compiler(inspector, "fd.name_changed=true"); fd_name_changed = std::move(compiler.compile()); }; @@ -760,7 +760,7 @@ static void run_fd_name_changed_test(bool use_sendmsg, // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { udps.start(); }; + run_callback_t test = [&](sinsp* inspector) { udps.start(); }; // // OUTPUT VALDATION @@ -824,7 +824,7 @@ TEST_F(sys_call_test, udp_client_server_multiple_connect_name_changed) { uint32_t num_name_changed_evts = 0; // INIT FILTER - before_open_t before_open = [&](sinsp* inspector) { + before_capture_t before_open = [&](sinsp* inspector) { sinsp_filter_compiler compiler(inspector, "fd.name_changed=true"); fd_name_changed = std::move(compiler.compile()); }; @@ -837,7 +837,7 @@ TEST_F(sys_call_test, udp_client_server_multiple_connect_name_changed) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { int sd; sd = socket(AF_INET, SOCK_DGRAM, 0); @@ -891,7 +891,7 @@ TEST_F(sys_call_test, statsd_client_snaplen) { "ipsum:" "18|c"; - before_open_t setup = [&](sinsp* inspector) { inspector->dynamic_snaplen(true); }; + before_capture_t setup = [&](sinsp* inspector) { inspector->dynamic_snaplen(true); }; // // FILTER @@ -904,7 +904,7 @@ TEST_F(sys_call_test, statsd_client_snaplen) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { // sendto with addr udp_client client(0x0100007F, false, 8125); client.m_payload = payload; @@ -938,9 +938,7 @@ TEST_F(sys_call_test, statsd_client_snaplen) { n++; }; - before_close_t cleanup = [&](sinsp* inspector) { inspector->dynamic_snaplen(false); }; - - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup, cleanup); }); + ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter, setup); }); EXPECT_EQ(4, n); } @@ -962,7 +960,7 @@ TEST_F(sys_call_test, statsd_client_no_snaplen) { // // INITIALIZATION // - run_callback_t test = [&](concurrent_object_handle inspector_handle) { + run_callback_t test = [&](sinsp* inspector) { // sendto with addr // Different port udp_client client(0x0100007F, false, 8126); diff --git a/test/libsinsp_e2e/unix_client_server.cpp b/test/libsinsp_e2e/unix_client_server.cpp index a668cb3e8a..e123ab0aad 100644 --- a/test/libsinsp_e2e/unix_client_server.cpp +++ b/test/libsinsp_e2e/unix_client_server.cpp @@ -95,14 +95,13 @@ TEST_F(sys_call_test, unix_client_server) { ends_with(ti->m_args[0], "unix_client_server.py"); } } - return false; }; // // INITIALIZATION // - run_callback_t test = [](concurrent_object_handle inspector) { + run_callback_t test = [](sinsp* inspector) { subprocess server("python3", {LIBSINSP_TEST_RESOURCES_PATH "/unix_client_server.py", "server"}); @@ -120,8 +119,6 @@ TEST_F(sys_call_test, unix_client_server) { captured_event_callback_t callback = [&](const callback_param& param) { sinsp_evt* evt = param.m_evt; - // std::cout << evt->get_name() << std::endl; - if(evt->get_type() == PPME_SOCKET_CONNECT_X) { std::string tuple = evt->get_param_value_str("tuple"); std::string addrs = tuple.substr(0, tuple.find(" ")); @@ -251,7 +248,14 @@ TEST_F(sys_call_test, unix_client_server) { // // OUTPUT VALDATION // - ASSERT_NO_FATAL_FAILURE({ event_capture::run(test, callback, filter); }); + ASSERT_NO_FATAL_FAILURE({ + event_capture::run(test, + callback, + filter, + event_capture::do_nothing, + event_capture::do_nothing, + libsinsp::events::sinsp_state_sc_set()); + }); EXPECT_FALSE(first_connect_or_accept_seen); EXPECT_EQ(8, callnum); } diff --git a/userspace/libpman/src/configuration.c b/userspace/libpman/src/configuration.c index 40e4e684fc..1f0e8ca26c 100644 --- a/userspace/libpman/src/configuration.c +++ b/userspace/libpman/src/configuration.c @@ -73,7 +73,7 @@ void pman_clear_state() { g_state.ringbuf_pos = 0; g_state.cons_pos = NULL; g_state.prod_pos = NULL; - g_state.inner_ringbuf_map_fd = 0; + g_state.inner_ringbuf_map_fd = -1; g_state.buffer_bytes_dim = 0; g_state.last_ring_read = -1; g_state.last_event_size = 0; diff --git a/userspace/libpman/src/lifecycle.c b/userspace/libpman/src/lifecycle.c index 68d0ad87be..51b2950976 100644 --- a/userspace/libpman/src/lifecycle.c +++ b/userspace/libpman/src/lifecycle.c @@ -67,6 +67,18 @@ void pman_close_probe() { g_state.stats = NULL; } + if(g_state.inner_ringbuf_map_fd != -1) { + close(g_state.inner_ringbuf_map_fd); + g_state.inner_ringbuf_map_fd = -1; + } + + for(int i = 0; i < MODERN_BPF_PROG_ATTACHED_MAX; i++) { + if(g_state.attached_progs_fds[i] != -1) { + close(g_state.attached_progs_fds[i]); + g_state.attached_progs_fds[i] = -1; + } + } + if(g_state.cons_pos) { free(g_state.cons_pos); g_state.cons_pos = NULL; diff --git a/userspace/libpman/src/ringbuffer.c b/userspace/libpman/src/ringbuffer.c index 4e4207b153..b99db59069 100644 --- a/userspace/libpman/src/ringbuffer.c +++ b/userspace/libpman/src/ringbuffer.c @@ -131,6 +131,7 @@ int pman_finalize_ringbuf_array_after_loading() { /* We don't need anymore the inner map, close it. */ close(g_state.inner_ringbuf_map_fd); + g_state.inner_ringbuf_map_fd = -1; /* Create ring buffer maps. */ for(int i = 0; i < g_state.n_required_buffers; i++) { diff --git a/userspace/libsinsp/container_engine/docker/docker_linux.cpp b/userspace/libsinsp/container_engine/docker/docker_linux.cpp index a6d75cb1c3..34e2f8ba1d 100644 --- a/userspace/libsinsp/container_engine/docker/docker_linux.cpp +++ b/userspace/libsinsp/container_engine/docker/docker_linux.cpp @@ -30,7 +30,7 @@ constexpr const cgroup_layout DOCKER_CGROUP_LAYOUT[] = {{"/", ""}, // non-syste {nullptr, nullptr}}; } -std::string docker_linux::m_docker_sock = "/var/run/docker.sock"; +std::string docker_linux::s_docker_sock = "/var/run/docker.sock"; bool docker_linux::resolve(sinsp_threadinfo* tinfo, bool query_os_for_missing_info) { std::string container_id, cgroup; @@ -40,7 +40,7 @@ bool docker_linux::resolve(sinsp_threadinfo* tinfo, bool query_os_for_missing_in } return resolve_impl(tinfo, - docker_lookup_request(container_id, m_docker_sock, CT_DOCKER, 0, false), + docker_lookup_request(container_id, s_docker_sock, CT_DOCKER, 0, false), query_os_for_missing_info); } @@ -61,7 +61,7 @@ void docker_linux::update_with_size(const std::string& container_id) { sinsp_container_info result; docker_lookup_request instruction(container_id, - m_docker_sock, + s_docker_sock, CT_DOCKER, 0, true /*request rw size*/); diff --git a/userspace/libsinsp/container_engine/docker/docker_linux.h b/userspace/libsinsp/container_engine/docker/docker_linux.h index a7c15d610e..393f488db5 100644 --- a/userspace/libsinsp/container_engine/docker/docker_linux.h +++ b/userspace/libsinsp/container_engine/docker/docker_linux.h @@ -10,7 +10,7 @@ class docker_linux : public docker_base { public: docker_linux(container_cache_interface& cache): docker_base(cache) {} - static void set_docker_sock(std::string docker_sock) { m_docker_sock = std::move(docker_sock); } + static void set_docker_sock(std::string docker_sock) { s_docker_sock = std::move(docker_sock); } // implement container_engine_base bool resolve(sinsp_threadinfo* tinfo, bool query_os_for_missing_info) override; @@ -18,7 +18,7 @@ class docker_linux : public docker_base { void update_with_size(const std::string& container_id) override; private: - static std::string m_docker_sock; + static std::string s_docker_sock; }; } // namespace container_engine diff --git a/userspace/libsinsp/container_engine/libvirt_lxc.cpp b/userspace/libsinsp/container_engine/libvirt_lxc.cpp index 161c87f377..676aa2985c 100644 --- a/userspace/libsinsp/container_engine/libvirt_lxc.cpp +++ b/userspace/libsinsp/container_engine/libvirt_lxc.cpp @@ -38,12 +38,19 @@ bool libvirt_lxc::match(sinsp_threadinfo* tinfo, sinsp_container_info& container } // - // systemd libvirt-lxc + // systemd libvirt-lxc: // pos = cgroup.find("-lxc\\x2"); if(pos != std::string::npos) { - size_t pos2 = cgroup.find(".scope"); - if(pos2 != std::string::npos && pos2 == cgroup.length() - sizeof(".scope") + 1) { + std::string delimiter = ".scope"; + size_t pos2 = cgroup.find(delimiter); + // For cgroups like: + // /machine.slice/machine-lxc\x2d2293906\x2dlibvirt\x2dcontainer.scope/libvirt, + // account for /libvirt below. + if(cgroup.find(".scope/libvirt") != std::string::npos) { + delimiter = ".scope/libvirt"; + } + if(pos2 != std::string::npos && pos2 == cgroup.length() - delimiter.length()) { container_info.m_type = CT_LIBVIRT_LXC; container_info.m_id = cgroup.substr(pos + sizeof("-lxc\\x2"), pos2 - pos - sizeof("-lxc\\x2"));