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

Forward Linux capabilities to child process #22

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

miray-sb
Copy link

When a user starts an AppImage from inside a shell that has certain Linux capabilities set, but the AppImage itself has none set, then the child process will have those capabilities enabled thus allowing the child process certain privileged functionality (e.g. listening on ports <= 1024).

However if capabilities are set on the AppImage file (using setcap) then the child process won't inherit any capabilities due to how capabilities are handled in that case (the Ambient set will be set to 0 which is what a process unaware of capabilities relies on).

This can be worked around by extracting the AppImage, setting the capabilities on the executable file and then running that. However this isn't a very convenient solution.

Thus we propose the extension contained in this merge request: before doing the execve for the child process all currently effective capabilities will be added to the Inheritable set and then all capabilities in both the Effective and Inheritable sets will be added to the Ambient set (only capabilities that are in both the Effective and Inheritable sets can be raised in the Ambient set).

This way a binary inside the AppImage can make use of privileged operations without running as root, but the system administrator still has full control what the AppImage can do.

…nd then apply all the capabilities in both the Effective and Inheritable sets to the Ambient set, so that the child process (which can be unaware of capabilities) can have its capabilities set accordingly.
@probonopd
Copy link
Member

Thank you very much for this contribution. Could you elaborate a bit on the use case? Running desktop Linux since the late 90s, I have never encountered Linux Capabilities. But then, I am mostly just running Linux Live ISOs. Under which circumstances would a normal desktop user benefit from this?

Can you think of any security risks this PR might introduce?

@miray-sb
Copy link
Author

miray-sb commented Apr 2, 2024

Thank you for your reply.

I'd suggest you to read the link I had mentioned, but as it is quite a big read (and I had to read it multiple times to fully grasp it myself), here a really short summary:

Linux capabilities had originally been introduced to Linux in version 2.2 (so January 1999) and partition the rights that the root user has so that processes can have a subset of them instead of the whole bunch when simply running as root (including setuid). Capabilities include things like listening on ports <= 1024 (CAP_NET_BIND_SERVICES), changing file ownership (CAP_CHOWN), sending SIGKILL to any process (CAP_KILL) or the ability to change the capabilities set on a file (CAP_SETFCAP). The ability to set the capabilities on a file had been introduced with Linux 2.6.24 and allows a system administrator (aka someone whose processes have the CAP_SETFCAP capability; e.g. root) to allow specific programs to have specific rights without granting it all rights that are granted to root.
While the set of capabilities is not as finegrained as it maybe should be (e.g. the capability CAP_SYS_ADMIN is quite a grab bag) it nevertheless allows to give applications only capabilities they need. This way, if an application has a security bug and is then compromised by an attacker then it can't go beyond what had been configured by the system administrator while with a process running as root this could be quite disastrous.

To give you an example where we use this: we have a product called BootCast which we're currently preparing for a Linux release (as an AppImage) and which provides PXE services, thus it needs to be able to listen to TFTP connections which require a port <= 1024 which in turn normally requires root privileges. Running an application - especially something as complex as a server application - as root can be quite a security problem. By using Linux capabilities this risk potential can be reduced, because a system administrator only needs to apply the CAP_NET_BIND_SERVICES capability to the application file and the Linux kernel will deal with the remainder.
On a typical desktop system “system administrator” will obviously be the same as “the one and only user”, but even then I'd say it's advantageous to not have something running as root if it isn't really needed (and if one doesn't use AppImages, but “normal” binaries then one can set things up correctly already).

Regarding security risks:
Right now a user that has the CAP_SETFCAP capability (e.g. root) is already able to extract the AppImage, set the capabilities and then have another user run it (e.g. by using some script to set up the necessary environment variables that the AppImage runtime usually sets up). This PR simply removes the step in between for the same effect.
Also when a file with capabilities is changed, then the Linux kernel will remove the capabilities of that file again, so it isn't possible to maliciously change a file that has capabilities set.
So as long as the capability system of the Linux kernel is working correctly I don't see any security risks with this, instead it has the potential to reduce the risk, cause one doesn't need to run an AppImage as root if some functionality requires privileges covered by a capability.

Feel free to ask other Linux users with more experience with capabilities before accepting this PR as I definitely wouldn't consider myself a “pro” here; we simply had a problem (namely running our product which is an AppImage without root privileges if possible) and implemented a solution (this PR), so we'll continue to maintain our fork due to us needing it, but we'd prefer this to be part of upstream obviously.

Also feel free to ask further questions, I'll do my best to answer them.

@probonopd
Copy link
Member

Thanks @miray-sb for your detailed answer. Indeed I didn't know about this before, but your explanation does make sense to me. I'd be interested to hear how @TheAssassin sees this, as on the basis of your explanation it seems reasonable to me to forward Linux capabilities to the child process, like you propose.

@probonopd
Copy link
Member

Pending @TheAssassin TODO list

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

Successfully merging this pull request may close these issues.

2 participants