-
Notifications
You must be signed in to change notification settings - Fork 165
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
container users and groups from process root #677
container users and groups from process root #677
Conversation
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved into userinfo_map_insert
auto &grplist = m_grouplist[container_id]; | ||
grplist[gid].gid = gid; | ||
strlcpy(grplist[gid].name, name, MAX_CREDENTIALS_STR_LEN); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved into groupinfo_map_insert
@@ -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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mind that sinsp_threadinfo::set_user
gets called by parse_chroot_exit
, parse_clone_exit
, parse_execve_exit
userspace/libsinsp/user.cpp
Outdated
if (name == NULL) | ||
{ | ||
name = "<NA>"; | ||
} | ||
if (home == NULL) | ||
{ | ||
home = "<NA>"; | ||
} | ||
if (shell == NULL) | ||
{ | ||
shell = "<NA>"; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Avoid putting <NA>
in cache on containers
userspace/libsinsp/user.cpp
Outdated
@@ -613,45 +691,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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This worked well with docker, but wasn't called by containerd.
I tested with a Job on k0s:
apiVersion: batch/v1
kind: Job
metadata:
name: custom-user
spec:
template:
spec:
securityContext:
runAsUser: 37
containers:
- name: custom-user
image: busybox:latest
command: ["sleep", "3600" ]
restartPolicy: Never
backoffLimit: 4
userspace/libsinsp/user.cpp
Outdated
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/"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From https://linux.die.net/man/5/proc:
/proc/[pid]/root
UNIX and Linux support the idea of a per-process root of the file system, set by the chroot system call. This file is a symbolic link that points to the process's root directory
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Credits to @gnosek for teaching me that. Credits to myself for a few days of experiments 🤣
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really nice!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love these changes!
I am going to give this a bit of testing asap and come back to you!
Also, the CI did explode :D Finally, i think we can also drop the container engines part to load the |
Yeah, the UT (which I actually wrote myself 😅) failed, I was eager to get some feedback and I didn't run them. |
7b0099f
to
900dab6
Compare
Cool! I am taking a closer look but it SGTM :) |
Yep, thanks! |
I found something weird: if I checkout |
I rebased the PR for adding e2e tests to CI on Tuesday, so whatever broke them is a change after that. I'll try to look into them ASAP, but if you guys find what is wrong, you can open a PR. |
Hi Mauro! I think the fix is #678 ! Thanks to Angelo <3 |
We can rebase on top of master :) |
900dab6
to
8ced729
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/approve
I really like this :)
We can cleanup the overalyfs things later, in a subsequent PR!
LGTM label has been added. Git tree hash: 7afc1b7e23321ddd423db20bd77bfe3181c566e3
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mmh on a better look, it seems like the container start is triggering an useradded event for host users (tested with sinsp-example:
sudo ./libsinsp/examples/sinsp-example --bpf driver/bpf/probe.o -f evt.type=useradded -o "%evt.arg[2] %evt.arg[5]"
- evt.arg[2] is user name
- evt.arg[5] is container id
It prints:
{"evt.arg[2]":"root","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"bin","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"daemon","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"mail","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"ftp","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"http","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"nobody","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"dbus","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"systemd-journal-remote","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"systemd-network","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"systemd-oom","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"systemd-resolve","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"systemd-timesync","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"systemd-coredump","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"uuidd","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"avahi","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"polkitd","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"rtkit","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"sddm","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"usbmux","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"federico","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"tss","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"git","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"geoclue","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"nm-openvpn","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"openvpn","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"brltty","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"sophosav","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"redis","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"dnsmasq","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"libvirt-qemu","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"mysql","evt.arg[5]":"2d4a2dd77f70"}
{"evt.arg[2]":"qemu","evt.arg[5]":"2d4a2dd77f70"}
Note the "federico" in there; these are the host users.
/hold |
Have HAVE_FGET__ENT representing _DEFAULT_SOURCE || _SVID_SOURCE, as a feature test for fgetpwent() / fgetgrent() Signed-off-by: Angelo Puglisi <[email protected]>
@Molter73 I'd like you to check the e2e part, if you have some time. Thanks in advance. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the delay @deepskyblue86! The changes on the e2e tests look solid, great to see someone actively using them! 😄
I left a few comments on the rest of the code, but overall the changes LGTM!
`readlink` does not append a null terminator to `buf`, so we might want to ensure at least one byte is left untouched in order to prevent possible buffer overruns Signed-off-by: Angelo Puglisi <[email protected]> Co-authored-by: Mauro Ezequiel Moltrasio <[email protected]>
Signed-off-by: Angelo Puglisi <[email protected]> Co-authored-by: Mauro Ezequiel Moltrasio <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/lgtm
LGTM label has been added. Git tree hash: 60da174f5558ca010ad752432af9a5eb3ecf1ca1
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just one question, LGTM otherwise :)
else if(uid != 0) | ||
{ | ||
// | ||
// When a container is running with a specific user and this | ||
// get called with 0, it's too early to make an attempt. | ||
// As a downside we won't load users for containers running as | ||
// root, but we will load them if e.g.docker exec -u <specific-user>. | ||
// | ||
user = m_inspector->m_usergroup_manager.add_container_user(m_container_id, m_pid, uid, m_inspector->is_live()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is it "too early"? Because we caught a thread switching into the container? What if the container is started as root?
What is uid
here? If we're calling this from all sorts of parsers, it's not a special uid, like the docker -u
user, right? So how does the uid != 0
check work?
Maybe hardcoding uid=0 as "root" would be good enough btw?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Why is it "too early"?
By trial and error, I found that the thread had the container id but wasn't really inside the container (i.e.runc:[1:CHILD]
in my tests). - What if the container is started as root?
We'll have<NA>
🤷 but if / when it switches to a different user we'll load the users. - What is
uid
here?
a)sinsp_threadinfo::set_user
is being called byparse_chroot_exit
,parse_clone_exit
,parse_execve_exit
,parse_setuid_exit
,parse_setresuid_exit
.
b) It's actually the user ofdocker -u
or k8srunAsUser
.
c) you can see that it's being tested (test/e2e/tests/test_process/test_container.py) by starting ahashicorp/http-echo:alpine
container with11:110
- Maybe hardcoding uid=0 as "root" would be good enough btw?
I was a bit uncertain about doing so, but if it's already two of us I'd go with that 😀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe hardcoding uid=0 as "root" would be good enough btw?
Makes sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/approve
/hold |
Sorry @gnosek i might have left behind your comment and approved :( |
Uh i already put this on hold 20d ago ahah @deepskyblue86 care to answer to grzeg question? |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: deepskyblue86, FedeDP, gnosek, Molter73 The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
/unhold |
What type of PR is this?
/kind feature
Any specific area of the project related to this PR?
/area libsinsp
/area tests
Does this PR require a change in the driver versions?
What this PR does / why we need it:
Introduce
add_container_user
andadd_container_group
.Those are called by
sinsp_threadinfo
set_user
/set_group
and load the information from /proc//root/etc.For that to work, the process running sinsp has to be privileged and in the host pid namespace.
For more information see
man 5 proc
.Which issue(s) this PR fixes:
Fixes #
Special notes for your reviewer:
Does this PR introduce a user-facing change?: