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

update(driver): handle processes sending open file descriptors via SCM_RIGHTS #1400

Merged
merged 10 commits into from
Oct 13, 2023

Conversation

loresuso
Copy link
Member

What type of PR is this?

Uncomment one (or more) /kind <> lines:

/kind bug

/kind cleanup

/kind design

/kind documentation

/kind failing-test

/kind feature

Any specific area of the project related to this PR?

Uncomment one (or more) /area <> lines:

/area API-version

/area build

/area CI

/area driver-kmod

/area driver-bpf

/area driver-modern-bpf

/area libscap-engine-bpf

/area libscap-engine-gvisor

/area libscap-engine-kmod

/area libscap-engine-modern-bpf

/area libscap-engine-nodriver

/area libscap-engine-noop

/area libscap-engine-source-plugin

/area libscap-engine-savefile

/area libscap-engine-udig

/area libscap

/area libpman

/area libsinsp

/area tests

/area proposals

Does this PR require a change in the driver versions?

/version driver-API-version-major

/version driver-API-version-minor

/version driver-API-version-patch

/version driver-SCHEMA-version-major

/version driver-SCHEMA-version-minor

/version driver-SCHEMA-version-patch

What this PR does / why we need it:
When using unix sockets, processes can pass open file descriptors to one another by using sendmsg and recmsg syscalls. This PR attempts to reflect this in the sinsp state. Whenever the recvmsg contains ancillary data, it checks for SCM_RIGHTS. If so, we proceed with a proc scan of the file descriptors of the receiving process, since it will have new open file descriptors that we missed.

Since we only want to update the file descriptors, this PR introduces a new platform API to scan only that and avoid parsing information about the receiving process that we already have in the sinsp state. This, plus the fact that we can consider the frequency of SCM_RIGHTS messages pretty low, should mean that we are not introducing a big performance penalty.

Which issue(s) this PR fixes:
#1364

Fixes #

Special notes for your reviewer:

Does this PR introduce a user-facing change?:

NONE

@github-actions
Copy link

github-actions bot commented Oct 10, 2023

Please double check driver/API_VERSION file. See versioning.

/hold

@loresuso loresuso changed the title update: handle processes sending open file descriptors via SCM_RIGHTS wip: update: handle processes sending open file descriptors via SCM_RIGHTS Oct 10, 2023
@loresuso loresuso force-pushed the update/shm-rights branch 2 times, most recently from 4fca071 to 537b173 Compare October 10, 2023 14:12
@poiana poiana added size/XL and removed size/L labels Oct 10, 2023
@loresuso loresuso force-pushed the update/shm-rights branch 3 times, most recently from 70c3c92 to 2c318a4 Compare October 11, 2023 08:46
if(etype == PPME_SOCKET_RECVMSG_X && evt->get_num_params() >= 5)
{
parinfo = evt->get_param(4);
if(parinfo->m_len > sizeof(struct cmsghdr))
Copy link
Member Author

Choose a reason for hiding this comment

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

Ensure there is room for the header and some more payload. In that case, SCM_RIGHTS could effectively have passed open file descriptors from one process to another

if(parinfo->m_len > sizeof(struct cmsghdr))
{
struct cmsghdr *cmsg = (struct cmsghdr *)parinfo->m_val;
if(cmsg->cmsg_type == SCM_RIGHTS)
Copy link
Member Author

@loresuso loresuso Oct 11, 2023

Choose a reason for hiding this comment

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

When using SCM_RIGHTS, we expect to have just one header, like in the example at the end of this page: https://linux.die.net/man/3/cmsg

struct msghdr msg = {0};
struct cmsghdr *cmsg;
int myfds[NUM_FD]; /* Contains the file descriptors to pass. */
char buf[CMSG_SPACE(sizeof myfds)];  /* ancillary data buffer */
int *fdptr;

msg.msg_control = buf;
msg.msg_controllen = sizeof buf;
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * NUM_FD);
/* Initialize the payload: */
fdptr = (int *) CMSG_DATA(cmsg);
memcpy(fdptr, myfds, NUM_FD * sizeof(int));
/* Sum of the length of all control messages in the buffer: */
msg.msg_controllen = cmsg->cmsg_len;

This is because SCM_RIGHTS offers natively the possibility to pass an array of file descriptors, so we won't need multiple headers. A quick check on the kernel source code also confirmed this.


/* Parameter 2: size (type: PT_UINT32) */
evt_test->assert_numeric_param(2, (uint32_t)FULL_MESSAGE_LEN);

Copy link
Member Author

Choose a reason for hiding this comment

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

I would add the check for parameter 4 here. Something like this:

evt_test->assert_tuple_unix_param(4, PPM_AF_UNIX, UNIX_SERVER);

The problem is that this only works with the modern bpf probe at the moment. I would be curious to solve this for the other two drivers. I think this is part of a bigger discussion, but the way we are constructing the tuple for UNIX sockets it's kind of wrong in my opinion:

as you can see, we are pushing two kernel pointers which are meaningless in userspace IMO. Plus, looks like the modern probe and the old drivers push a different tuple in this particular case.


snprintf(proc_dir, sizeof(proc_dir), "%s/proc/%d/", scap_get_host_root(), tinfo->pid);

return scap_fd_scan_fd_dir(linux_platform, &platform->m_proclist, proc_dir, tinfo, &sockets_by_ns, &num_fds_ret, lasterr);
Copy link
Member Author

@loresuso loresuso Oct 11, 2023

Choose a reason for hiding this comment

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

This is the function that is responsible for calling the sinsp proc callbacks for the tinfo and each scanned fd

Copy link
Contributor

@jasondellaluce jasondellaluce left a comment

Choose a reason for hiding this comment

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

LGTM

@@ -65,6 +66,7 @@ struct scap_platform_vtable
bool (*is_thread_alive)(struct scap_platform*, int64_t pid, int64_t tid, const char* comm);
int32_t (*get_global_pid)(struct scap_platform*, int64_t *pid, char *error);
int32_t (*get_threadlist)(struct scap_platform* platform, struct ppm_proclist_info **procinfo_p, char *lasterr);
int32_t (*get_fdlist)(struct scap_platform* platform, struct scap_threadinfo *tinfo, char *lasterr);
Copy link
Contributor

Choose a reason for hiding this comment

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

cc @gnosek about scap platform new method

@FedeDP
Copy link
Contributor

FedeDP commented Oct 12, 2023

I triggered a run of kernel testing framework against HEAD of the branch: https://github.com/falcosecurity/libs/actions/runs/6493764036

EDIT: ops, wrong; i need to push an upstream branch first.

@FedeDP
Copy link
Contributor

FedeDP commented Oct 12, 2023

@loresuso
Copy link
Member Author

Thanks Fede!

@FedeDP
Copy link
Contributor

FedeDP commented Oct 12, 2023

No new issues (same as on master!)

Arm64:

KERNEL CMAKE-CONFIGURE KMOD BUILD KMOD SCAP-OPEN BPF-PROBE BUILD BPF-PROBE SCAP-OPEN MODERN-BPF SCAP-OPEN
amazonlinux2-5.4 🟢 🟢 🟢 🟢 🟢 🟡
amazonlinux2022-5.15 🟢 🟢 🟢 🟢 🟢 🟢
fedora-6.2 🟢 🟢 🟢 🟢 🟢 🟢
oraclelinux-4.14 🟢 🟢 🟢 🟡 🟡 🟡
oraclelinux-5.15 🟢 🟢 🟢 🟢 🟢 🟢
ubuntu-6.3 🟢 🟢 🟢 🟢 🟢 🟢

amd64:

KERNEL CMAKE-CONFIGURE KMOD BUILD KMOD SCAP-OPEN BPF-PROBE BUILD BPF-PROBE SCAP-OPEN MODERN-BPF SCAP-OPEN
amazonlinux2-4.19 🟢 🟢 🟢 🟢 🟢 🟡
amazonlinux2-5.10 🟢 🟢 🟢 🟢 🟢 🟢
amazonlinux2-5.15 🟢 🟢 🟢 🟢 🟢 🟢
amazonlinux2-5.4 🟢 🟢 🟢 🟢 🟢 🟡
amazonlinux2022-5.15 🟢 🟢 🟢 🟢 🟢 🟢
amazonlinux2023-6.1 🟢 🟢 🟢 🟢 🟢 🟢
archlinux-6.0 🟢 🟢 🟢 🟢 🟢 🟢
centos-3.10 🟢 🟢 🟢 🟡 🟡 🟡
centos-4.18 🟢 🟢 🟢 🟢
centos-5.14 🟢 🟢 🟢 🟢 🟢 🟢
fedora-5.17 🟢 🟢 🟢 🟢
fedora-5.8 🟢 🟢 🟢 🟢 🟢
fedora-6.2 🟢 🟢 🟢 🟢 🟢 🟢
oraclelinux-3.10 🟢 🟢 🟢 🟡 🟡 🟡
oraclelinux-4.14 🟢 🟢 🟢 🟢 🟢 🟡
oraclelinux-5.15 🟢 🟢 🟢 🟢 🟢 🟢
oraclelinux-5.4 🟢 🟢 🟢 🟢 🟢 🟡
ubuntu-4.15 🟢 🟢 🟢 🟢 🟢 🟡
ubuntu-6.3 🟢 🟢 🟢 🟢 🟢 🟢

Copy link
Member

@Andreagit97 Andreagit97 left a comment

Choose a reason for hiding this comment

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

Amazing work!

userspace/libscap/linux/scap_procs.c Show resolved Hide resolved
userspace/libscap/scap_platform_api.h Outdated Show resolved Hide resolved
userspace/libscap/scap_platform_impl.h Outdated Show resolved Hide resolved
userspace/libsinsp/parsers.cpp Show resolved Hide resolved
userspace/libsinsp/parsers.cpp Show resolved Hide resolved
…remove useless forward decl

Signed-off-by: Lorenzo Susini <[email protected]>
@FedeDP
Copy link
Contributor

FedeDP commented Oct 12, 2023

/milestone next-driver

@poiana poiana added this to the next-driver milestone Oct 12, 2023
@loresuso
Copy link
Member Author

loresuso commented Oct 12, 2023

Looks like the test on ancillary_data is flaky. Sometimes the recvmsg event can't be found, which is really weird
EDIT: I have now tried to put the exact pid in the wait call. Let's run this a couple of times to see if that was the issue.
RE-EDIT: looks like it works now

@loresuso loresuso force-pushed the update/shm-rights branch 3 times, most recently from 0dd985c to 73ad7c5 Compare October 13, 2023 08:54
Copy link
Member

@Andreagit97 Andreagit97 left a comment

Choose a reason for hiding this comment

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

/approve

@poiana
Copy link
Contributor

poiana commented Oct 13, 2023

LGTM label has been added.

Git tree hash: 867e8603ae65d8adbb184f842155c5f79276ee57

Copy link
Contributor

@FedeDP FedeDP left a comment

Choose a reason for hiding this comment

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

/approve

@poiana
Copy link
Contributor

poiana commented Oct 13, 2023

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: Andreagit97, FedeDP, loresuso

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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@FedeDP
Copy link
Contributor

FedeDP commented Oct 13, 2023

/hold cancel

@poiana poiana merged commit 9daa2db into falcosecurity:master Oct 13, 2023
64 checks passed
@Andreagit97 Andreagit97 changed the title update: handle processes sending open file descriptors via SCM_RIGHTS update(driver): handle processes sending open file descriptors via SCM_RIGHTS Jan 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants