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

Socket FDs sharing control #33

Closed
sm1ling-knight opened this issue Jun 7, 2024 · 7 comments
Closed

Socket FDs sharing control #33

sm1ling-knight opened this issue Jun 7, 2024 · 7 comments

Comments

@sm1ling-knight
Copy link

Motivation of socket access-control feature is to restrict actions of adding sockets in a sandboxed process. This can be useful to limit the range of allowed protocols or even to disable the addition of new sockets in sandboxed process.

Processes can share socket FDs with each other. Linux currently supports the following mechanisms:

  • Inherit socket FD from parent process after fork'ing.
  • Pass socket FD using UNIX domain sockets (see SCM_RIGHTS in unix(7)).
  • Duplicate socket FD from another process using pidfd_getfd(2) syscall.
  • ???

While inheritance in the first case isn't an issue, since landlock doesn't care about the actions performed before sandboxing, the other 2 cases seem to be an issue. A process can get sockets of undesirable family and type after sandboxing by obtaining corresponding FD from another process.

Landlock should support restriction on sharing socket FDs between processes in order to properly limit desired protocol range.

Related to #6

@gnoack
Copy link

gnoack commented Jun 9, 2024

From pidfd_getfd(2):

Permission to duplicate another process's file descriptor is
governed by a ptrace access mode PTRACE_MODE_ATTACH_REALCREDS
check (see ptrace(2)).

In my understanding, Landlock already restricts the directions in which ptrace accesses are granted (you can only ptrace processes in the same domain or in nested domains). Compare https://elixir.bootlin.com/linux/latest/source/tools/testing/selftests/landlock/ptrace_test.c

If I am reading the man page right, I suspect this might already be covered?

@gnoack
Copy link

gnoack commented Jun 9, 2024

Aside from pidfd_getfd(2):

To obtain an opened file from a higher-privileged process,
the higher-privileged process must voluntarily pass it down.
And if an attacker can exert that control over the higher-privileged process,
they already have control over the file descriptor anyway?

This is the case both for SCM_RIGHTS over Unix Domain Sockets,
and for inheriting FDs from parent to child processes.

For pidfd_getfd(2), the originating process does not need to play along,
but that is already restricted through Landlock's ptrace restrictions, I think.

It helps me to think of file descriptors as "capabilities" (in the sense of https://en.wikipedia.org/wiki/Capability-based_security, not in the sense of Linux capabilities). When viewing things that way, I believe this lets us create processes with sound security properties?

I might well be missing something here or not understanding your goal correctly...
Are there concrete scenarios that you can not secure without restricting SCM_RIGHTS and pidfd_getfd() further than they already are?

@l0kod
Copy link
Member

l0kod commented Jun 10, 2024

pidfd_getfd(2) should indeed already be handled.

About FD passing (with SCM_RIGHTS), this can be seen as a performance improvement which doesn't directly impact security: instead of sending a FD, the same process could just be a proxy and interpret commands (e.g. read/write to one of its own FD and forward the result), which would result to the same action (malicious or not).

If we want to be sure that a sandbox doesn't use a specific protocol, then we first need to make sure that this sandbox doesn't have an open channel (e.g. socket, other IPCs) with a more-privileged process willing to help, which would be a kind of sandbox escape. Ultimately, this is not something the kernel/Landlock can really help with because it is a matter of user space semantic and user space policy on the service side. However, if the sandbox is initially secure (e.g. well-controlled socket and other IPCs access), it should be OK. Other security mechanism such as polkit should be used to extend the security policy to non-sandboxed processes if they are exposed inside sandboxes.

@l0kod
Copy link
Member

l0kod commented Jun 10, 2024

It helps me to think of file descriptors as "capabilities" (in the sense of https://en.wikipedia.org/wiki/Capability-based_security, not in the sense of Linux capabilities). When viewing things that way, I believe this lets us create processes with sound security properties?

Talking about capabilities, I wanted to highlight the current behavior in TCP port control. Landlock restricts connect and bind actions according to the caller, not the creator of the socket. I think it makes sense because a new connection/binding has a close semantic to opening a file i.e., getting access to new data.

However, we need to keep that in mind for ongoing and future access controls, especially dealing with FD, sockets, and other IPCs. There are pros and cons for each "mode", but we could also handle both mode if needed (with explicit Landlock request).

@sm1ling-knight
Copy link
Author

sm1ling-knight commented Aug 21, 2024

Hello @l0kod, @gnoack ! Sorry for the late reply and thank you for the detailed answer.

It turns out that the LANDLOCK_ACCESS_SOCKET_CREATE is the only needed access right related to socket object. I've also thought about setsockopt control, but if it is really useful, it'll be better to have fine-grained control for that as for the net rules.

Does everyone agree that we don't need any changes to the API and a single access right for this rule is OK?

@l0kod
Copy link
Member

l0kod commented Sep 5, 2024

It turns out that the LANDLOCK_ACCESS_SOCKET_CREATE is the only needed access right related to socket object. I've also thought about setsockopt control, but if it is really useful, it'll be better to have fine-grained control for that as for the net rules.

I agree. I think we can control meaningful setsockopt() feature with more generic access rights like for your #40 example.

Does everyone agree that we don't need any changes to the API and a single access right for this rule is OK?

It looks good to me. Control of socket creation will be a great and simple way to improve control over the network.

@sm1ling-knight
Copy link
Author

Thank you!

Considering the results of the discussion, I close the issue.

@sm1ling-knight sm1ling-knight closed this as not planned Won't fix, can't repro, duplicate, stale Sep 5, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants