From e9574f6b8f010b02030e31e2750e19fef7c64d52 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Mon, 9 Dec 2024 14:25:16 +0100 Subject: [PATCH] chore(userspace/libsinsp): move user group manager on container_id changed refresh to a RAII object. Also, avoid subscribing to container manager "container removed" callback; instead, use same RAII object to check whether init pid for the container did exit. Signed-off-by: Federico Di Pierro --- userspace/libsinsp/dumper.cpp | 5 +- userspace/libsinsp/event.cpp | 6 +- userspace/libsinsp/parsers.cpp | 38 ++------- userspace/libsinsp/sinsp.cpp | 34 ++++---- userspace/libsinsp/sinsp.h | 4 +- userspace/libsinsp/test/filterchecks/evt.cpp | 6 +- userspace/libsinsp/test/filterchecks/user.cpp | 16 ++-- .../libsinsp/test/sinsp_with_test_input.h | 1 + userspace/libsinsp/threadinfo.cpp | 19 ++--- userspace/libsinsp/user.cpp | 29 ++----- userspace/libsinsp/user.h | 80 ++++++++++++++++--- 11 files changed, 131 insertions(+), 107 deletions(-) diff --git a/userspace/libsinsp/dumper.cpp b/userspace/libsinsp/dumper.cpp index 542ea4f21c..02e7264c79 100644 --- a/userspace/libsinsp/dumper.cpp +++ b/userspace/libsinsp/dumper.cpp @@ -22,6 +22,7 @@ limitations under the License. #include #include #include +#include sinsp_dumper::sinsp_dumper() { m_dumper = NULL; @@ -67,7 +68,7 @@ void sinsp_dumper::open(sinsp* inspector, const std::string& filename, bool comp inspector->m_thread_manager->dump_threads_to_file(m_dumper); inspector->m_container_manager.dump_containers(*this); - inspector->m_usergroup_manager.dump_users_groups(*this); + inspector->m_usergroup_manager->dump_users_groups(*this); // ask registered ASYNC plugins for a dump of their state for(auto& p : inspector->m_plugin_manager->plugins()) { @@ -94,7 +95,7 @@ void sinsp_dumper::fdopen(sinsp* inspector, int fd, bool compress) { inspector->m_thread_manager->dump_threads_to_file(m_dumper); inspector->m_container_manager.dump_containers(*this); - inspector->m_usergroup_manager.dump_users_groups(*this); + inspector->m_usergroup_manager->dump_users_groups(*this); // ask registered ASYNC plugins for a dump of their state for(auto& p : inspector->m_plugin_manager->plugins()) { diff --git a/userspace/libsinsp/event.cpp b/userspace/libsinsp/event.cpp index d65565ff74..4f6f1c956e 100644 --- a/userspace/libsinsp/event.cpp +++ b/userspace/libsinsp/event.cpp @@ -36,6 +36,7 @@ limitations under the License. #include #include +#include #include #include @@ -1325,7 +1326,7 @@ const char *sinsp_evt::get_param_as_str(uint32_t id, sinsp_threadinfo *tinfo = get_thread_info(); scap_userinfo *user_info = NULL; if(tinfo) { - user_info = m_inspector->m_usergroup_manager.get_user(tinfo->m_container_id, val); + user_info = m_inspector->m_usergroup_manager->get_user(tinfo->m_container_id, val); } if(user_info != NULL) { strcpy_sanitized(&m_resolved_paramstr_storage[0], @@ -1354,7 +1355,8 @@ const char *sinsp_evt::get_param_as_str(uint32_t id, sinsp_threadinfo *tinfo = get_thread_info(); scap_groupinfo *group_info = NULL; if(tinfo) { - group_info = m_inspector->m_usergroup_manager.get_group(tinfo->m_container_id, val); + group_info = + m_inspector->m_usergroup_manager->get_group(tinfo->m_container_id, val); } if(group_info != NULL) { strcpy_sanitized(&m_resolved_paramstr_storage[0], diff --git a/userspace/libsinsp/parsers.cpp b/userspace/libsinsp/parsers.cpp index d14c8ebdf9..939cbc0cf2 100644 --- a/userspace/libsinsp/parsers.cpp +++ b/userspace/libsinsp/parsers.cpp @@ -41,6 +41,7 @@ limitations under the License. #include #include #include +#include #if !defined(MINIMAL_BUILD) && !defined(__EMSCRIPTEN__) #include @@ -1274,12 +1275,6 @@ void sinsp_parser::parse_clone_exit_caller(sinsp_evt *evt, int64_t child_tid) { return; } - /* Refresh user / group */ - if(new_child->m_container_id.empty() == false) { - new_child->set_group(new_child->m_gid); - new_child->set_user(new_child->m_uid); - } - /* If there's a listener, invoke it */ if(m_inspector->get_observer()) { m_inspector->get_observer()->on_clone(evt, new_child.get(), tid_collision); @@ -1764,12 +1759,6 @@ void sinsp_parser::parse_clone_exit_child(sinsp_evt *evt) { */ evt->set_tinfo(new_child.get()); - /* Refresh user / group */ - if(new_child->m_container_id.empty() == false) { - new_child->set_group(new_child->m_gid); - new_child->set_user(new_child->m_uid); - } - // // If there's a listener, invoke it // @@ -2239,15 +2228,6 @@ void sinsp_parser::parse_execve_exit(sinsp_evt *evt) { // evt->get_tinfo()->compute_program_hash(); - // - // Refresh user / group - // if we happen to change container id - // - if(container_id != evt->get_tinfo()->m_container_id) { - evt->get_tinfo()->set_group(evt->get_tinfo()->m_gid); - evt->get_tinfo()->set_user(evt->get_tinfo()->m_uid); - } - // // If there's a listener, invoke it // @@ -4894,9 +4874,9 @@ void sinsp_parser::parse_user_evt(sinsp_evt *evt) { if(evt->get_scap_evt()->type == PPME_USER_ADDED_E) { m_inspector->m_usergroup_manager - .add_user(std::string(container_id), -1, uid, gid, name, home, shell); + ->add_user(std::string(container_id), -1, uid, gid, name, home, shell); } else { - m_inspector->m_usergroup_manager.rm_user(std::string(container_id), uid); + m_inspector->m_usergroup_manager->rm_user(std::string(container_id), uid); } } @@ -4907,9 +4887,9 @@ void sinsp_parser::parse_group_evt(sinsp_evt *evt) { std::string_view container_id = evt->get_param(2)->as(); if(evt->get_scap_evt()->type == PPME_GROUP_ADDED_E) { - m_inspector->m_usergroup_manager.add_group(container_id.data(), -1, gid, name.data()); + m_inspector->m_usergroup_manager->add_group(container_id.data(), -1, gid, name.data()); } else { - m_inspector->m_usergroup_manager.rm_group(container_id.data(), gid); + m_inspector->m_usergroup_manager->rm_group(container_id.data(), gid); } } @@ -4992,14 +4972,6 @@ void sinsp_parser::parse_chroot_exit(sinsp_evt *evt) { m_inspector->m_container_manager.resolve_container( evt->get_tinfo(), m_inspector->is_live() || m_inspector->is_syscall_plugin()); - // - // Refresh user / group - // if we happen to change container id - // - if(container_id != evt->get_tinfo()->m_container_id) { - evt->get_tinfo()->set_group(evt->get_tinfo()->m_gid); - evt->get_tinfo()->set_user(evt->get_tinfo()->m_uid); - } } } diff --git a/userspace/libsinsp/sinsp.cpp b/userspace/libsinsp/sinsp.cpp index 7b116f73b3..2714f64623 100644 --- a/userspace/libsinsp/sinsp.cpp +++ b/userspace/libsinsp/sinsp.cpp @@ -45,6 +45,7 @@ limitations under the License. #include #include #include +#include /** * This is the maximum size assigned to the concurrent asynchronous event @@ -148,7 +149,6 @@ sinsp::sinsp(bool with_metrics): m_lastevent_ts(0), m_host_root(scap_get_host_root()), m_container_manager(this), - m_usergroup_manager(this), m_async_events_queue(DEFAULT_ASYNC_EVENT_QUEUE_SIZE), m_suppressed_comms(), m_inited(false) { @@ -163,6 +163,7 @@ sinsp::sinsp(bool with_metrics): m_is_dumping = false; m_parser = std::make_unique(this); m_thread_manager = std::make_unique(this); + m_usergroup_manager = std::make_unique(this); m_max_fdtable_size = MAX_FD_TABLE_SIZE; m_containers_purging_scan_time_ns = DEFAULT_INACTIVE_CONTAINER_SCAN_TIME_S * ONE_SECOND_IN_NS; m_usergroups_purging_scan_time_ns = DEFAULT_DELETED_USERS_GROUPS_SCAN_TIME_S * ONE_SECOND_IN_NS; @@ -359,7 +360,7 @@ void sinsp::init() { } void sinsp::set_import_users(bool import_users) { - m_usergroup_manager.m_import_users = import_users; + m_usergroup_manager->m_import_users = import_users; } /*=============================== OPEN METHODS ===============================*/ @@ -376,11 +377,7 @@ void sinsp::open_common(scap_open_args* oargs, /* We need to save the actual mode and the engine used by the inspector. */ m_mode = mode; - oargs->import_users = m_usergroup_manager.m_import_users; - // We need to subscribe to container manager notifiers before - // scap starts scanning proc. - m_usergroup_manager.subscribe_container_mgr(); - + oargs->import_users = m_usergroup_manager->m_import_users; oargs->log_fn = &sinsp_scap_log_fn; oargs->proc_scan_timeout_ms = m_proc_scan_timeout_ms; oargs->proc_scan_log_interval_ms = m_proc_scan_log_interval_ms; @@ -990,17 +987,17 @@ void sinsp::import_user_list() { if(ul) { for(j = 0; j < ul->nusers; j++) { - m_usergroup_manager.add_user("", - -1, - ul->users[j].uid, - ul->users[j].gid, - ul->users[j].name, - ul->users[j].homedir, - ul->users[j].shell); + m_usergroup_manager->add_user("", + -1, + ul->users[j].uid, + ul->users[j].gid, + ul->users[j].name, + ul->users[j].homedir, + ul->users[j].shell); } for(j = 0; j < ul->ngroups; j++) { - m_usergroup_manager.add_group("", -1, ul->groups[j].gid, ul->groups[j].name); + m_usergroup_manager->add_group("", -1, ul->groups[j].gid, ul->groups[j].name); } } } @@ -1267,7 +1264,7 @@ int32_t sinsp::next(sinsp_evt** puevt) { } if(m_auto_usergroups_purging && !is_offline()) { - m_usergroup_manager.clear_host_users_groups(); + m_usergroup_manager->clear_host_users_groups(); } // @@ -1297,6 +1294,11 @@ int32_t sinsp::next(sinsp_evt** puevt) { { // Object that uses RAII to enable event filtered out flag sinsp_evt_filter evt_filter(evt); + // Object that uses RAII to automatically update user/group associated with a threadinfo + // upon threadinfo's container_id changes. + // Since the threadinfo state might get changed from a plugin parser, + // evaluate this one after all parsers get run. + user_group_updater usr_grp_updater(evt); if(!evt->is_filtered_out()) { // diff --git a/userspace/libsinsp/sinsp.h b/userspace/libsinsp/sinsp.h index ddf254c95f..cff68e14d0 100644 --- a/userspace/libsinsp/sinsp.h +++ b/userspace/libsinsp/sinsp.h @@ -73,7 +73,6 @@ limitations under the License. #include #include #include -#include #include #include @@ -91,6 +90,7 @@ class sinsp_filter; class sinsp_plugin; class sinsp_plugin_manager; class sinsp_observer; +class sinsp_usergroup_manager; /*! \brief The user agent string to use for any libsinsp connection, can be changed at compile time @@ -1062,7 +1062,7 @@ class SINSP_PUBLIC sinsp : public capture_stats_source { sinsp_container_manager m_container_manager; - sinsp_usergroup_manager m_usergroup_manager; + std::unique_ptr m_usergroup_manager; // // True if the command line argument is set to show container information diff --git a/userspace/libsinsp/test/filterchecks/evt.cpp b/userspace/libsinsp/test/filterchecks/evt.cpp index 8e1cfda7b5..29a26499bd 100644 --- a/userspace/libsinsp/test/filterchecks/evt.cpp +++ b/userspace/libsinsp/test/filterchecks/evt.cpp @@ -195,7 +195,7 @@ TEST_F(sinsp_with_test_input, EVT_FILTER_check_evt_arg_uid) { // we are adding a user on the host so the `pid` parameter is not considered ASSERT_TRUE(m_inspector.m_usergroup_manager - .add_user(container_id, 0, user_id, 6, "test", "/test", "/bin/test")); + ->add_user(container_id, 0, user_id, 6, "test", "/test", "/bin/test")); // Now we should have the necessary info ASSERT_EQ(get_field_as_string(evt, "evt.arg.uid"), "test"); @@ -203,8 +203,8 @@ TEST_F(sinsp_with_test_input, EVT_FILTER_check_evt_arg_uid) { ASSERT_EQ(get_field_as_string(evt, "evt.args"), "uid=5(test)"); // We remove the user, and the fields should be empty again - m_inspector.m_usergroup_manager.rm_user(container_id, user_id); - ASSERT_FALSE(m_inspector.m_usergroup_manager.get_user(container_id, user_id)); + m_inspector.m_usergroup_manager->rm_user(container_id, user_id); + ASSERT_FALSE(m_inspector.m_usergroup_manager->get_user(container_id, user_id)); ASSERT_EQ(get_field_as_string(evt, "evt.arg.uid"), ""); ASSERT_EQ(get_field_as_string(evt, "evt.arg[0]"), ""); diff --git a/userspace/libsinsp/test/filterchecks/user.cpp b/userspace/libsinsp/test/filterchecks/user.cpp index b1425b855c..8abc943459 100644 --- a/userspace/libsinsp/test/filterchecks/user.cpp +++ b/userspace/libsinsp/test/filterchecks/user.cpp @@ -28,7 +28,7 @@ TEST_F(sinsp_with_test_input, USER_FILTER_extract_from_existent_user_entry) { open_inspector(); - m_inspector.m_usergroup_manager.add_user("", INIT_TID, 1000, 1000, "foo", "/foo", "/bin/bash"); + m_inspector.m_usergroup_manager->add_user("", INIT_TID, 1000, 1000, "foo", "/foo", "/bin/bash"); std::string path = "/home/file.txt"; int64_t fd = 3; @@ -49,7 +49,7 @@ TEST_F(sinsp_with_test_input, USER_FILTER_extract_from_existent_user_entry) { ASSERT_EQ(get_field_as_string(evt, "user.loginname"), "root"); // Now remove the user - m_inspector.m_usergroup_manager.rm_user("", 1000); + m_inspector.m_usergroup_manager->rm_user("", 1000); ASSERT_EQ(get_field_as_string(evt, "user.uid"), "1000"); ASSERT_EQ(get_field_as_string(evt, "user.loginuid"), "0"); ASSERT_EQ(get_field_as_string(evt, "user.name"), ""); @@ -59,7 +59,7 @@ TEST_F(sinsp_with_test_input, USER_FILTER_extract_from_existent_user_entry) { ASSERT_EQ(get_field_as_string(evt, "user.loginname"), "root"); // Add back a new user - m_inspector.m_usergroup_manager.add_user("", INIT_TID, 1000, 1000, "bar", "/bar", "/bin/bash"); + m_inspector.m_usergroup_manager->add_user("", INIT_TID, 1000, 1000, "bar", "/bar", "/bin/bash"); ASSERT_EQ(get_field_as_string(evt, "user.uid"), "1000"); ASSERT_EQ(get_field_as_string(evt, "user.loginuid"), "0"); ASSERT_EQ(get_field_as_string(evt, "user.name"), "bar"); @@ -76,11 +76,11 @@ TEST_F(sinsp_with_test_input, USER_FILTER_extract_from_default_user_entry) { // The entry gets created when the inspector is opened and its threadtable created. // Since default thread uid is 0, the entry is created with "root" name and "/root" homedir. - ASSERT_NE(m_inspector.m_usergroup_manager.get_user("", 0), nullptr); + ASSERT_NE(m_inspector.m_usergroup_manager->get_user("", 0), nullptr); // remove the loaded "root" user to test defaults for uid 0 - m_inspector.m_usergroup_manager.rm_user("", 0); - ASSERT_EQ(m_inspector.m_usergroup_manager.get_user("", 0), nullptr); + m_inspector.m_usergroup_manager->rm_user("", 0); + ASSERT_EQ(m_inspector.m_usergroup_manager->get_user("", 0), nullptr); std::string path = "/home/file.txt"; int64_t fd = 3; @@ -109,7 +109,7 @@ TEST_F(sinsp_with_test_input, USER_FILTER_extract_from_existent_user_entry_witho // Creating the entry in the user group manager will override // the one created by the inspector threadtable initial load. // Since we set "" metadatas, we don't expect any metadata in the output fields. - m_inspector.m_usergroup_manager.add_user("", INIT_TID, 0, 0, "", "", ""); + m_inspector.m_usergroup_manager->add_user("", INIT_TID, 0, 0, "", "", ""); std::string path = "/home/file.txt"; int64_t fd = 3; @@ -135,7 +135,7 @@ TEST_F(sinsp_with_test_input, USER_FILTER_extract_from_loaded_user_entry) { // Creating the entry in the user group manager will override // the one created by the inspector threadtable initial load. // Since we set **empty** metadata, we expect metadata to be loaded from the system. - m_inspector.m_usergroup_manager.add_user("", INIT_TID, 0, 0, {}, {}, {}); + m_inspector.m_usergroup_manager->add_user("", INIT_TID, 0, 0, {}, {}, {}); std::string path = "/home/file.txt"; int64_t fd = 3; diff --git a/userspace/libsinsp/test/sinsp_with_test_input.h b/userspace/libsinsp/test/sinsp_with_test_input.h index 5ec82aeffb..b945cdaead 100644 --- a/userspace/libsinsp/test/sinsp_with_test_input.h +++ b/userspace/libsinsp/test/sinsp_with_test_input.h @@ -22,6 +22,7 @@ limitations under the License. #include #include +#include #include #include #include diff --git a/userspace/libsinsp/threadinfo.cpp b/userspace/libsinsp/threadinfo.cpp index 01d581f0c9..ba9f3abb8d 100644 --- a/userspace/libsinsp/threadinfo.cpp +++ b/userspace/libsinsp/threadinfo.cpp @@ -27,6 +27,7 @@ limitations under the License. #include #include #include +#include constexpr static const char* s_thread_table_name = "threads"; @@ -532,30 +533,30 @@ std::string sinsp_threadinfo::get_exepath() const { void sinsp_threadinfo::set_user(uint32_t uid) { m_uid = uid; - scap_userinfo* user = m_inspector->m_usergroup_manager.get_user(m_container_id, uid); + scap_userinfo* user = m_inspector->m_usergroup_manager->get_user(m_container_id, uid); if(!user) { auto notify = m_inspector->is_live() || m_inspector->is_syscall_plugin(); // For uid 0 force set root related infos if(uid == 0) { m_inspector->m_usergroup_manager - .add_user(m_container_id, m_pid, uid, m_gid, "root", "/root", {}, notify); + ->add_user(m_container_id, m_pid, uid, m_gid, "root", "/root", {}, notify); } else { m_inspector->m_usergroup_manager - .add_user(m_container_id, m_pid, uid, m_gid, {}, {}, {}, notify); + ->add_user(m_container_id, m_pid, uid, m_gid, {}, {}, {}, notify); } } } void sinsp_threadinfo::set_group(uint32_t gid) { m_gid = gid; - scap_groupinfo* group = m_inspector->m_usergroup_manager.get_group(m_container_id, gid); + scap_groupinfo* group = m_inspector->m_usergroup_manager->get_group(m_container_id, gid); if(!group) { auto notify = m_inspector->is_live() || m_inspector->is_syscall_plugin(); // For gid 0 force set root related info if(gid == 0) { - m_inspector->m_usergroup_manager.add_group(m_container_id, m_pid, gid, "root", notify); + m_inspector->m_usergroup_manager->add_group(m_container_id, m_pid, gid, "root", notify); } else { - m_inspector->m_usergroup_manager.add_group(m_container_id, m_pid, gid, {}, notify); + m_inspector->m_usergroup_manager->add_group(m_container_id, m_pid, gid, {}, notify); } } } @@ -565,7 +566,7 @@ void sinsp_threadinfo::set_loginuid(uint32_t loginuid) { } scap_userinfo* sinsp_threadinfo::get_user() const { - auto user = m_inspector->m_usergroup_manager.get_user(m_container_id, m_uid); + auto user = m_inspector->m_usergroup_manager->get_user(m_container_id, m_uid); if(user != nullptr) { return user; } @@ -579,7 +580,7 @@ scap_userinfo* sinsp_threadinfo::get_user() const { } scap_groupinfo* sinsp_threadinfo::get_group() const { - auto group = m_inspector->m_usergroup_manager.get_group(m_container_id, m_gid); + auto group = m_inspector->m_usergroup_manager->get_group(m_container_id, m_gid); if(group != nullptr) { return group; } @@ -590,7 +591,7 @@ scap_groupinfo* sinsp_threadinfo::get_group() const { } scap_userinfo* sinsp_threadinfo::get_loginuser() const { - auto user = m_inspector->m_usergroup_manager.get_user(m_container_id, m_loginuid); + auto user = m_inspector->m_usergroup_manager->get_user(m_container_id, m_loginuid); if(user != nullptr) { return user; } diff --git a/userspace/libsinsp/user.cpp b/userspace/libsinsp/user.cpp index 69c7b5daa1..158816295f 100644 --- a/userspace/libsinsp/user.cpp +++ b/userspace/libsinsp/user.cpp @@ -17,7 +17,6 @@ limitations under the License. */ #include -#include #include #include #include @@ -125,18 +124,6 @@ sinsp_usergroup_manager::sinsp_usergroup_manager(sinsp* inspector) } // clang-format on -void sinsp_usergroup_manager::subscribe_container_mgr() { - // Do nothing if subscribe_container_mgr() is called in capture mode, because - // events shall not be sent as they will be loaded from capture file. - if(m_import_users && (m_inspector->is_live() || m_inspector->is_syscall_plugin())) { - // Emplace container manager listener to delete container users upon container deletion - m_inspector->m_container_manager.subscribe_on_remove_container( - [&](const sinsp_container_info &cinfo) -> void { - delete_container_users_groups(cinfo); - }); - } -} - void sinsp_usergroup_manager::dump_users_groups(sinsp_dumper &dumper) { for(const auto &it : m_userlist) { std::string container_id = it.first; @@ -163,27 +150,25 @@ void sinsp_usergroup_manager::dump_users_groups(sinsp_dumper &dumper) { } } -void sinsp_usergroup_manager::delete_container_users_groups(const sinsp_container_info &cinfo) { - auto usrlist = get_userlist(cinfo.m_id); - if(usrlist) { +void sinsp_usergroup_manager::delete_container(const std::string &container_id) { + if(auto usrlist = get_userlist(container_id)) { for(auto &u : *usrlist) { // We do not have a thread id here, as a removed container // means that it has no tIDs anymore. - notify_user_changed(&u.second, cinfo.m_id, false); + notify_user_changed(&u.second, container_id, false); } } - auto grplist = get_grouplist(cinfo.m_id); - if(grplist) { + if(auto grplist = get_grouplist(container_id)) { for(auto &g : *grplist) { // We do not have a thread id here, as a removed container // means that it has no tIDs anymore. - notify_group_changed(&g.second, cinfo.m_id, false); + notify_group_changed(&g.second, container_id, false); } } - m_userlist.erase(cinfo.m_id); - m_grouplist.erase(cinfo.m_id); + m_userlist.erase(container_id); + m_grouplist.erase(container_id); } bool sinsp_usergroup_manager::clear_host_users_groups() { diff --git a/userspace/libsinsp/user.h b/userspace/libsinsp/user.h index 4151c74858..7534c75ff9 100644 --- a/userspace/libsinsp/user.h +++ b/userspace/libsinsp/user.h @@ -22,13 +22,10 @@ limitations under the License. #include #include #include -#include #include -#include +#include class sinsp; -class sinsp_dumper; -class sinsp_evt; namespace libsinsp { namespace procfs_utils { class ns_helper; @@ -71,10 +68,6 @@ class sinsp_usergroup_manager { explicit sinsp_usergroup_manager(sinsp *inspector); ~sinsp_usergroup_manager() = default; - // Do not call subscribe_container_mgr() in capture mode, because - // events shall not be sent as they will be loaded from capture file. - void subscribe_container_mgr(); - void dump_users_groups(sinsp_dumper &dumper); /*! @@ -147,6 +140,8 @@ class sinsp_usergroup_manager { bool clear_host_users_groups(); + void delete_container(const std::string &container_id); + // // User and group tables // @@ -179,8 +174,6 @@ class sinsp_usergroup_manager { const std::string &container_id, uint16_t ev_type); - void delete_container_users_groups(const sinsp_container_info &cinfo); - void notify_user_changed(const scap_userinfo *user, const std::string &container_id, bool added = true); @@ -213,4 +206,71 @@ class sinsp_usergroup_manager { std::unique_ptr m_ns_helper; }; +// RAII struct to manage threadinfos automatic user/group refresh +// upon container_id updates. +struct user_group_updater { + explicit user_group_updater(sinsp_evt *evt) { + m_check_cleanup = false; + switch(evt->get_type()) { + case PPME_PROCEXIT_E: + case PPME_PROCEXIT_1_E: + m_check_cleanup = true; + // falltrough + case PPME_SYSCALL_CLONE_11_X: + case PPME_SYSCALL_CLONE_16_X: + case PPME_SYSCALL_CLONE_17_X: + case PPME_SYSCALL_CLONE_20_X: + case PPME_SYSCALL_FORK_X: + case PPME_SYSCALL_FORK_17_X: + case PPME_SYSCALL_FORK_20_X: + case PPME_SYSCALL_VFORK_X: + case PPME_SYSCALL_VFORK_17_X: + case PPME_SYSCALL_VFORK_20_X: + case PPME_SYSCALL_CLONE3_X: + case PPME_SYSCALL_EXECVE_8_X: + case PPME_SYSCALL_EXECVE_13_X: + case PPME_SYSCALL_EXECVE_14_X: + case PPME_SYSCALL_EXECVE_15_X: + case PPME_SYSCALL_EXECVE_16_X: + case PPME_SYSCALL_EXECVE_17_X: + case PPME_SYSCALL_EXECVE_18_X: + case PPME_SYSCALL_EXECVE_19_X: + case PPME_SYSCALL_EXECVEAT_X: + case PPME_SYSCALL_CHROOT_X: + m_evt = evt; + if(m_evt->get_tinfo() != nullptr) { + m_container_id = m_evt->get_tinfo()->m_container_id; + } + break; + default: + m_evt = nullptr; + break; + } + } + + ~user_group_updater() { + if(m_evt != nullptr && m_evt->get_tinfo() != nullptr) { + auto tinfo = m_evt->get_tinfo(); + if(tinfo->m_container_id != m_container_id) { + // Refresh user/group + tinfo->set_group(tinfo->m_gid); + tinfo->set_user(tinfo->m_uid); + } else if(m_check_cleanup && !tinfo->m_container_id.empty()) { + if(tinfo->m_vtid == tinfo->m_vpid && tinfo->m_vpid == 1) { + // main container process left, clean up user and groups for the container + const auto inspector = m_evt->get_inspector(); + if(inspector->m_usergroup_manager->m_import_users && + (inspector->is_live() || inspector->is_syscall_plugin())) { + inspector->m_usergroup_manager->delete_container(tinfo->m_container_id); + } + } + } + } + } + + bool m_check_cleanup; + sinsp_evt *m_evt; + std::string m_container_id; +}; + #endif // FALCOSECURITY_LIBS_USER_H