Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(userspace/libsinsp): user id 0 or group id 0 default values #2177

Merged
merged 4 commits into from
Dec 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions userspace/libsinsp/sinsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,9 +285,8 @@
m_inited = true;
}

void sinsp::set_import_users(bool import_users, bool user_details) {
void sinsp::set_import_users(bool import_users) {

Check warning on line 288 in userspace/libsinsp/sinsp.cpp

View check run for this annotation

Codecov / codecov/patch

userspace/libsinsp/sinsp.cpp#L288

Added line #L288 was not covered by tests
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaned up unused flag.

m_usergroup_manager.m_import_users = import_users;
m_usergroup_manager.m_user_details_enabled = user_details;
}

/*=============================== OPEN METHODS ===============================*/
Expand Down
13 changes: 1 addition & 12 deletions userspace/libsinsp/sinsp.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,18 +271,12 @@ class SINSP_PUBLIC sinsp : public capture_stats_source {
creating them can increase the startup time. Moreover, they contain
information that could be privacy sensitive.

\param user_details if set to false, no extended user information will be
stored in sinsp_threadinfo, only user id/group id will be available. By
default thread information is enriched with the full set of user
information, i.e. name, homedir, shell, group name. The parameter
controls this behavior, an can be used to reduce memory footprint.

\note default behavior is import_users=true, user_details=true

@throws a sinsp_exception containing the error string is thrown in case
of failure.
*/
void set_import_users(bool import_users, bool user_details = true);
void set_import_users(bool import_users);

/*!
\brief temporarily pauses event capture.
Expand Down Expand Up @@ -738,11 +732,6 @@ class SINSP_PUBLIC sinsp : public capture_stats_source {
*/
inline bool is_debug_enabled() const { return m_isdebug_enabled; }

/*!
\brief Returns true if extended user information is collected.
*/
inline bool is_user_details_enabled() { return m_usergroup_manager.m_user_details_enabled; }

/*!
\brief Set a flag indicating if the command line requested to show container information.

Expand Down
153 changes: 153 additions & 0 deletions userspace/libsinsp/test/filterchecks/user.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2024 The Falco Authors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

#include <test/helpers/threads_helpers.h>

TEST_F(sinsp_with_test_input, USER_FILTER_extract_from_existent_user_entry) {
add_default_init_thread();

auto& thread = m_threads.front();
thread.uid = 1000;
thread.gid = 1000;
thread.loginuid = 0;

open_inspector();

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;

auto evt = add_event_advance_ts(increasing_ts(),
INIT_TID,
PPME_SYSCALL_OPEN_E,
fd,
path.c_str(),
(uint32_t)PPM_O_RDWR | PPM_O_CREAT,
(uint32_t)0);
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"), "foo");
ASSERT_EQ(get_field_as_string(evt, "user.homedir"), "/foo");
ASSERT_EQ(get_field_as_string(evt, "user.shell"), "/bin/bash");
// Loginname default at root for 0 uid without an user entry in user group manager.
ASSERT_EQ(get_field_as_string(evt, "user.loginname"), "root");

// Now remove the user
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"), "<NA>");
ASSERT_EQ(get_field_as_string(evt, "user.homedir"), "<NA>");
ASSERT_EQ(get_field_as_string(evt, "user.shell"), "<NA>");
// Loginname default at root for 0 uid without an user entry in user group manager.
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");
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");
ASSERT_EQ(get_field_as_string(evt, "user.homedir"), "/bar");
ASSERT_EQ(get_field_as_string(evt, "user.shell"), "/bin/bash");
// Loginname default at root for 0 uid without an user entry in user group manager.
ASSERT_EQ(get_field_as_string(evt, "user.loginname"), "root");
}

TEST_F(sinsp_with_test_input, USER_FILTER_extract_from_default_user_entry) {
add_default_init_thread();

open_inspector();

// 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);

// 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);

std::string path = "/home/file.txt";
int64_t fd = 3;

auto evt = add_event_advance_ts(increasing_ts(),
INIT_TID,
PPME_SYSCALL_OPEN_E,
fd,
path.c_str(),
(uint32_t)PPM_O_RDWR | PPM_O_CREAT,
(uint32_t)0);

// For non-existent entries whose uid is 0, "root" and "/root"
// are automatically filled by threadinfo::get_user() method.
ASSERT_EQ(get_field_as_string(evt, "user.uid"), "0");
ASSERT_EQ(get_field_as_string(evt, "user.name"), "root");
ASSERT_EQ(get_field_as_string(evt, "user.homedir"), "/root");
ASSERT_EQ(get_field_as_string(evt, "user.shell"), "<NA>");
}

TEST_F(sinsp_with_test_input, USER_FILTER_extract_from_existent_user_entry_without_metadata) {
add_default_init_thread();

open_inspector();

// 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, "", "", "");

std::string path = "/home/file.txt";
int64_t fd = 3;

auto evt = add_event_advance_ts(increasing_ts(),
INIT_TID,
PPME_SYSCALL_OPEN_E,
fd,
path.c_str(),
(uint32_t)PPM_O_RDWR | PPM_O_CREAT,
(uint32_t)0);
ASSERT_EQ(get_field_as_string(evt, "user.uid"), "0");
ASSERT_EQ(get_field_as_string(evt, "user.name"), "");
ASSERT_EQ(get_field_as_string(evt, "user.homedir"), "");
ASSERT_EQ(get_field_as_string(evt, "user.shell"), "");
}

TEST_F(sinsp_with_test_input, USER_FILTER_extract_from_loaded_user_entry) {
add_default_init_thread();

open_inspector();

// 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, {}, {}, {});

std::string path = "/home/file.txt";
int64_t fd = 3;

auto evt = add_event_advance_ts(increasing_ts(),
INIT_TID,
PPME_SYSCALL_OPEN_E,
fd,
path.c_str(),
(uint32_t)PPM_O_RDWR | PPM_O_CREAT,
(uint32_t)0);
ASSERT_EQ(get_field_as_string(evt, "user.uid"), "0");
ASSERT_EQ(get_field_as_string(evt, "user.name"), "root");
ASSERT_EQ(get_field_as_string(evt, "user.homedir"), "/root");
}
43 changes: 30 additions & 13 deletions userspace/libsinsp/threadinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,8 +535,14 @@ void sinsp_threadinfo::set_user(uint32_t 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();
m_inspector->m_usergroup_manager
.add_user(m_container_id, m_pid, uid, m_gid, {}, {}, {}, notify);
// 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);
} else {
m_inspector->m_usergroup_manager
.add_user(m_container_id, m_pid, uid, m_gid, {}, {}, {}, notify);
}
}
}

Expand All @@ -545,32 +551,33 @@ void sinsp_threadinfo::set_group(uint32_t 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();
m_inspector->m_usergroup_manager.add_group(m_container_id, m_pid, gid, {}, notify);
// 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);
} else {
m_inspector->m_usergroup_manager.add_group(m_container_id, m_pid, gid, {}, notify);
}
}
}

void sinsp_threadinfo::set_loginuid(uint32_t loginuid) {
m_loginuid = loginuid;
}

scap_userinfo* sinsp_threadinfo::get_user(uint32_t id) const {
auto user = m_inspector->m_usergroup_manager.get_user(m_container_id, id);
scap_userinfo* sinsp_threadinfo::get_user() const {
auto user = m_inspector->m_usergroup_manager.get_user(m_container_id, m_uid);
if(user != nullptr) {
return user;
}
static scap_userinfo usr{};
usr.uid = id;
usr.uid = m_uid;
usr.gid = m_gid;
strlcpy(usr.name, id == 0 ? "root" : "<NA>", sizeof(usr.name));
strlcpy(usr.homedir, id == 0 ? "/root" : "<NA>", sizeof(usr.homedir));
strlcpy(usr.name, m_uid == 0 ? "root" : "<NA>", sizeof(usr.name));
strlcpy(usr.homedir, m_uid == 0 ? "/root" : "<NA>", sizeof(usr.homedir));
strlcpy(usr.shell, "<NA>", sizeof(usr.shell));
return &usr;
}

scap_userinfo* sinsp_threadinfo::get_user() const {
return get_user(m_uid);
}

scap_groupinfo* sinsp_threadinfo::get_group() const {
auto group = m_inspector->m_usergroup_manager.get_group(m_container_id, m_gid);
if(group != nullptr) {
Expand All @@ -583,7 +590,17 @@ scap_groupinfo* sinsp_threadinfo::get_group() const {
}

scap_userinfo* sinsp_threadinfo::get_loginuser() const {
return get_user(m_loginuid);
auto user = m_inspector->m_usergroup_manager.get_user(m_container_id, m_loginuid);
if(user != nullptr) {
return user;
}
static scap_userinfo usr{};
usr.uid = m_loginuid;
usr.gid = m_gid;
strlcpy(usr.name, m_loginuid == 0 ? "root" : "<NA>", sizeof(usr.name));
strlcpy(usr.homedir, m_loginuid == 0 ? "/root" : "<NA>", sizeof(usr.homedir));
strlcpy(usr.shell, "<NA>", sizeof(usr.shell));
return &usr;
}

void sinsp_threadinfo::set_args(const char* args, size_t len) {
Expand Down
2 changes: 0 additions & 2 deletions userspace/libsinsp/threadinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -608,8 +608,6 @@ class SINSP_PUBLIC sinsp_threadinfo : public libsinsp::state::table_entry {
uint32_t& alen,
std::string& rem) const;

scap_userinfo* get_user(uint32_t id) const;

//
// Parameters that can't be accessed directly because they could be in the
// parent thread info
Expand Down
1 change: 0 additions & 1 deletion userspace/libsinsp/user.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ using namespace std;
// clang-format off
sinsp_usergroup_manager::sinsp_usergroup_manager(sinsp* inspector)
: m_import_users(true)
, m_user_details_enabled(true)
, m_last_flush_time_ns(0)
, m_inspector(inspector)
, m_host_root(m_inspector->get_host_root())
Expand Down
2 changes: 0 additions & 2 deletions userspace/libsinsp/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,6 @@ class sinsp_usergroup_manager {
//
bool m_import_users;

bool m_user_details_enabled;

private:
scap_userinfo *add_host_user(uint32_t uid,
uint32_t gid,
Expand Down
Loading