diff --git a/userspace/libsinsp/threadinfo.cpp b/userspace/libsinsp/threadinfo.cpp index ea3bbb8631..992217644b 100644 --- a/userspace/libsinsp/threadinfo.cpp +++ b/userspace/libsinsp/threadinfo.cpp @@ -505,8 +505,15 @@ void sinsp_threadinfo::set_user(uint32_t uid) scap_userinfo *user = m_inspector->m_usergroup_manager.get_user(m_container_id, uid); if (!user) { - // this can fail if import_user is disabled - user = m_inspector->m_usergroup_manager.add_user(m_container_id, uid, m_group.gid, NULL, NULL, NULL, m_inspector->is_live()); + // these can fail if import_user is disabled + if(m_container_id.empty()) + { + user = m_inspector->m_usergroup_manager.add_user(m_container_id, uid, m_group.gid, NULL, NULL, NULL, m_inspector->is_live()); + } + else + { + user = m_inspector->m_usergroup_manager.add_container_user(m_container_id, m_pid, uid, m_inspector->is_live()); + } } if (user) @@ -528,8 +535,15 @@ void sinsp_threadinfo::set_group(uint32_t gid) scap_groupinfo *group = m_inspector->m_usergroup_manager.get_group(m_container_id, gid); if (!group) { - // this can fail if import_user is disabled - group = m_inspector->m_usergroup_manager.add_group(m_container_id, gid, NULL, m_inspector->is_live()); + // these can fail if import_user is disabled + if(m_container_id.empty()) + { + group = m_inspector->m_usergroup_manager.add_group(m_container_id, gid, NULL, m_inspector->is_live()); + } + else + { + group = m_inspector->m_usergroup_manager.add_container_group(m_container_id, m_pid, gid, m_inspector->is_live()); + } } if (group) diff --git a/userspace/libsinsp/user.cpp b/userspace/libsinsp/user.cpp index 19a7682caa..aeb4619b20 100644 --- a/userspace/libsinsp/user.cpp +++ b/userspace/libsinsp/user.cpp @@ -141,10 +141,6 @@ void sinsp_usergroup_manager::subscribe_container_mgr() m_inspector->m_container_manager.subscribe_on_remove_container([&](const sinsp_container_info &cinfo) -> void { delete_container_users_groups(cinfo); }); - - m_inspector->m_container_manager.subscribe_on_new_container([&](const sinsp_container_info&cinfo, sinsp_threadinfo *tinfo) -> void { - load_from_container(cinfo.m_id, cinfo.m_overlayfs_root); - }); } } @@ -235,6 +231,42 @@ bool sinsp_usergroup_manager::clear_host_users_groups() return res; } +scap_userinfo *sinsp_usergroup_manager::userinfo_map_insert( + userinfo_map &map, + uint32_t uid, + uint32_t gid, + const char *name, + const char *home, + const char *shell) +{ + ASSERT(name); + ASSERT(home); + ASSERT(shell); + + auto &usr = map[uid]; + usr.uid = uid; + usr.gid = gid; + strlcpy(usr.name, name, MAX_CREDENTIALS_STR_LEN); + strlcpy(usr.homedir, home, SCAP_MAX_PATH_SIZE); + strlcpy(usr.shell, shell, SCAP_MAX_PATH_SIZE); + + return &usr; +} + +scap_groupinfo *sinsp_usergroup_manager::groupinfo_map_insert( + groupinfo_map &map, + uint32_t gid, + const char *name) +{ + ASSERT(name); + + auto &grp = map[gid]; + grp.gid = gid; + strlcpy(grp.name, name, MAX_CREDENTIALS_STR_LEN); + + return &grp; +} + scap_userinfo *sinsp_usergroup_manager::add_user(const string &container_id, uint32_t uid, uint32_t gid, const char *name, const char *home, const char *shell, bool notify) { g_logger.format(sinsp_logger::SEV_DEBUG, @@ -249,59 +281,98 @@ scap_userinfo *sinsp_usergroup_manager::add_user(const string &container_id, uin scap_userinfo *usr = get_user(container_id, uid); if (!usr) { -#ifdef HAVE_PWD_H - struct passwd *p = nullptr; - if (container_id.empty() && !name) + bool do_notify{false}; + if (name) { + usr = userinfo_map_insert( + m_userlist[container_id], + uid, + gid, + name, + home, + shell); + do_notify = true; + } + else if (container_id.empty()) + { +#ifdef HAVE_PWD_H // On Host, try to load info from db - p = __getpwuid(uid); + auto* p = __getpwuid(uid); if (p) { - name = p->pw_name; - home = p->pw_dir; - shell = p->pw_shell; + usr = userinfo_map_insert( + m_userlist[container_id], + p->pw_uid, + p->pw_gid, + p->pw_name, + p->pw_dir, + p->pw_shell); + do_notify = true; } - } #endif - - if (name == NULL) - { - name = ""; - } - if (home == NULL) - { - home = ""; } - if (shell == NULL) - { - shell = ""; - } - - auto &userlist = m_userlist[container_id]; - userlist[uid].uid = uid; - userlist[uid].gid = gid; - strlcpy(userlist[uid].name, name, MAX_CREDENTIALS_STR_LEN); - strlcpy(userlist[uid].homedir, home, SCAP_MAX_PATH_SIZE); - strlcpy(userlist[uid].shell, shell, SCAP_MAX_PATH_SIZE); - if (notify) + if (notify && do_notify) { - notify_user_changed(&userlist[uid], container_id); + notify_user_changed(usr, container_id); } - - usr = &userlist[uid]; } - else if (name != NULL) + else if (name != NULL) { // Update user if it was already there strlcpy(usr->name, name, MAX_CREDENTIALS_STR_LEN); strlcpy(usr->homedir, home, SCAP_MAX_PATH_SIZE); strlcpy(usr->shell, shell, SCAP_MAX_PATH_SIZE); - } return usr; } +scap_userinfo *sinsp_usergroup_manager::add_container_user(const std::string &container_id, int64_t pid, uint32_t uid, bool notify) +{ + ASSERT(!container_id.empty()); + if(container_id.empty()) + { + return nullptr; + } + + scap_userinfo *retval{nullptr}; + +#if defined HAVE_PWD_H && defined HAVE_FGET__ENT + std::string proc_root_etc = s_host_root + "/proc/" + std::to_string(pid) + "/root/etc/"; + + auto passwd_in_container = proc_root_etc + "passwd"; + auto pwd_file = fopen(passwd_in_container.c_str(), "r"); + if(pwd_file) + { + auto &userlist = m_userlist[container_id]; + while(auto p = fgetpwent(pwd_file)) + { + // Here we cache all container users + auto *usr = userinfo_map_insert( + userlist, + p->pw_uid, + p->pw_gid, + p->pw_name, + p->pw_dir, + p->pw_shell); + + if(notify) + { + notify_user_changed(usr, container_id); + } + + if(uid == p->pw_uid) + { + retval = usr; + } + } + fclose(pwd_file); + } +#endif + + return retval; +} + bool sinsp_usergroup_manager::rm_user(const string &container_id, uint32_t uid, bool notify) { g_logger.format(sinsp_logger::SEV_DEBUG, @@ -334,35 +405,31 @@ scap_groupinfo *sinsp_usergroup_manager::add_group(const string &container_id, u scap_groupinfo *gr = get_group(container_id, gid); if (!gr) { -#ifdef HAVE_GRP_H - struct group *p = nullptr; - if (container_id.empty() && !name) + bool do_notify{false}; + if (name) { + gr = groupinfo_map_insert(m_grouplist[container_id], gid, name); + do_notify = true; + } + else if (container_id.empty()) + { +#ifdef HAVE_GRP_H // On Host, try to load info from db - p = __getgrgid(gid); - if (p) + auto* g = __getgrgid(gid); + if (g) { - name = p->gr_name; + gr = groupinfo_map_insert(m_grouplist[container_id], g->gr_gid, g->gr_name); + do_notify = true; } - } #endif - - if (name == NULL) - { - name = ""; } - auto &grplist = m_grouplist[container_id]; - grplist[gid].gid = gid; - strlcpy(grplist[gid].name, name, MAX_CREDENTIALS_STR_LEN); - - if (notify) + if (notify && do_notify) { - notify_group_changed(&grplist[gid], container_id, true); + notify_group_changed(gr, container_id, true); } - gr = &grplist[gid]; } - else if (name != NULL) + else if (name != NULL) { // Update group if it was already there strlcpy(gr->name, name, MAX_CREDENTIALS_STR_LEN); @@ -371,6 +438,46 @@ scap_groupinfo *sinsp_usergroup_manager::add_group(const string &container_id, u return gr; } +scap_groupinfo *sinsp_usergroup_manager::add_container_group(const std::string &container_id, int64_t pid, uint32_t gid, bool notify) +{ + ASSERT(!container_id.empty()); + if(container_id.empty()) + { + return nullptr; + } + + scap_groupinfo *retval{nullptr}; + +#if defined HAVE_GRP_H && defined HAVE_FGET__ENT + std::string proc_root_etc = s_host_root + "/proc/" + std::to_string(pid) + "/root/etc/"; + + auto group_in_container = proc_root_etc + "group"; + auto group_file = fopen(group_in_container.c_str(), "r"); + if(group_file) + { + auto &grouplist = m_grouplist[container_id]; + while(auto g = fgetgrent(group_file)) + { + // Here we cache all container groups + auto *gr = groupinfo_map_insert(grouplist, g->gr_gid, g->gr_name); + + if(notify) + { + notify_group_changed(gr, container_id, true); + } + + if(gid == g->gr_gid) + { + retval = gr; + } + } + fclose(group_file); + } +#endif + + return retval; +} + bool sinsp_usergroup_manager::rm_group(const string &container_id, uint32_t gid, bool notify) { g_logger.format(sinsp_logger::SEV_DEBUG, @@ -619,43 +726,3 @@ void sinsp_usergroup_manager::notify_group_changed(const scap_groupinfo *group, m_inspector->m_pending_state_evts.push(cevt); #endif } - -void sinsp_usergroup_manager::load_from_container(const std::string &container_id, const std::string &overlayfs_root) -{ - if (!m_import_users) - { - return; - } - - if (overlayfs_root.empty()) - { - // Avoid loading from host - return; - } - -#if defined HAVE_PWD_H && defined HAVE_FGET__ENT - auto passwd_in_container = overlayfs_root + "/etc/passwd"; - auto pwd_file = fopen(passwd_in_container.c_str(), "r"); - if(pwd_file) - { - while(auto p = fgetpwent(pwd_file)) - { - add_user(container_id, p->pw_uid, p->pw_gid, p->pw_name, p->pw_dir, p->pw_shell, true); - } - fclose(pwd_file); - } -#endif - -#if defined HAVE_GRP_H && defined HAVE_FGET__ENT - auto group_in_container = overlayfs_root + "/etc/group"; - auto grp_file = fopen(group_in_container.c_str(), "r"); - if(grp_file) - { - while(auto g = fgetgrent(grp_file)) - { - add_group(container_id, g->gr_gid, g->gr_name, true); - } - fclose(grp_file); - } -#endif -} diff --git a/userspace/libsinsp/user.h b/userspace/libsinsp/user.h index 913755a39c..640c616d8c 100644 --- a/userspace/libsinsp/user.h +++ b/userspace/libsinsp/user.h @@ -116,10 +116,13 @@ class sinsp_usergroup_manager scap_userinfo *add_user(const std::string &container_id, uint32_t uid, uint32_t gid, const char *name, const char *home, const char *shell, bool notify = false); scap_groupinfo *add_group(const std::string &container_id, uint32_t gid, const char *name, bool notify = false); + + scap_userinfo *add_container_user(const std::string &container_id, int64_t pid, uint32_t uid, bool notify = false); + scap_groupinfo *add_container_group(const std::string &container_id, int64_t pid, uint32_t gid, bool notify = false); + bool rm_user(const std::string &container_id, uint32_t uid, bool notify = false); bool rm_group(const std::string &container_id, uint32_t gid, bool notify = false); - void load_from_container(const std::string &container_id, const std::string &overlayfs_root); bool clear_host_users_groups(); // @@ -140,8 +143,23 @@ class sinsp_usergroup_manager void notify_user_changed(const scap_userinfo *user, const std::string &container_id, bool added = true); void notify_group_changed(const scap_groupinfo *group, const std::string &container_id, bool added = true); - std::unordered_map> m_userlist; - std::unordered_map> m_grouplist; + using userinfo_map = std::unordered_map; + using groupinfo_map = std::unordered_map; + + scap_userinfo *userinfo_map_insert( + userinfo_map &map, + uint32_t uid, + uint32_t gid, + const char *name, + const char *home, + const char *shell); + scap_groupinfo *groupinfo_map_insert( + groupinfo_map &map, + uint32_t gid, + const char *name); + + std::unordered_map m_userlist; + std::unordered_map m_grouplist; uint64_t m_last_flush_time_ns; sinsp *m_inspector; };