landlock-lsm / linux

Linux kernel - See Landlock issues
https://git.kernel.org/pub/scm/linux/kernel/git/mic/linux.git/
Other
33 stars 9 forks source link

Socket FDs sharing control #33

Open sm1ling-knight opened 3 weeks ago

sm1ling-knight commented 3 weeks ago

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:

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 commented 3 weeks ago

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 commented 3 weeks ago

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 commented 2 weeks ago

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 commented 2 weeks ago

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).