I think many details of your question could apply equally to avahi-daemon
, which I looked at recently. (I might have missed another detail that differs though). Running avahi-daemon in a chroot has many advantages, in case avahi-daemon is compromised. These include:
- it cannot read any users home directory and exfiltrate private information.
- it cannot exploit bugs in other programs by writing to /tmp. There is at least one whole category of such bugs. E.g. https://www.google.co.uk/search?q=tmp+race+security+bug
- it cannot open any unix socket file which is outside the chroot, which other daemons may be listening and reading messages on.
Point 3 could be particularly nice when you're not using dbus or similar... I think avahi-daemon uses dbus, so it makes sure to keep access to the system dbus even from inside the chroot. If you don't need the ability to send messages on the system dbus, denying that ability might be quite a nice security feature.
managing it with systemd unit file
Note that if avahi-daemon was re-written, it could potentially choose to rely on systemd for security, and use e.g. ProtectHome
. I proposed a change to avahi-daemon to add these protections as an extra layer, along with some additional protections that are not guaranteed by chroot. You can see the full list of options I proposed here:
https://github.com/lathiat/avahi/pull/181/commits/67a7b10049c58d6afeebdc64ffd2023c5a93d49a
It looks like there are more restrictions which I could have used if avahi-daemon did not use chroot itself, some of which are mentioned in the commit message. I'm not sure how much this applies though.
Note, the protections I used would not have limited the daemon from opening unix socket files (point 3 above).
Another approach would be to use SELinux. However you would kind of be tying your application to that sub-set of Linux distributions. The reason I thought of SELinux positively here, is that SELinux restricts the access that processes have on dbus, in a fine-grained way. For example, I think you could often expect that systemd
would not be in the list of bus names that you needed to be able to send messages to :-).
"I was wondering, if using systemd sandboxing more secure than chroot/setuid/umask/..."
Summary: why not both? Let's decode the above a bit :-).
If you think about point 3, using chroot provides more confinement. ProtectHome= and its friends don't even try to be as restrictive as chroot. (For example, none of the named systemd options blacklists /run
, where we tend to put unix socket files).
chroot shows that restricting filesystem access can be a very powerful, but not everything on Linux is a file :-). There are systemd options that can restrict other things, that are not files. This is useful if the program is compromised, you can reduce the kernel features available to it, which it might try to exploit a vulnerability in. For example avahi-daemon doesn't need bluetooth sockets and I guess your web server doesn't either :-). So don't give it access to the AF_BLUETOOTH address family. Just whitelist AF_INET, AF_INET6, and maybe AF_UNIX, using the RestrictAddressFamilies=
option.
Please read the docs for each option you use. Some options are be more effective in combination with others, and some are not available on all CPU architectures. (Not because the CPU is bad, but because the Linux port for that CPU wasn't as nicely designed. I think).
(There's a general principle here. It's more secure if you can write lists of what you want to allow, not what you want to deny. Like defining a chroot gives you a list of files you're allowed to access, and this more robust than saying you want to block /home
).
In principle, you could apply all the same restrictions yourself before setuid(). It's all just code which you could copy from systemd. However, systemd unit options should be significantly easier to write, and since they are in a standard format they should be easier to read and review.
So I can highly recommend just reading through the sandboxing section of man systemd.exec
on your target platform. But if you want the most secure design possible, I wouldn't be afraid to try chroot
(and then drop root
privileges) in your program as well. There is a tradeoff here. Using chroot
imposes some constraints on your overall design. If you already have a design that uses chroot, and it seems to do what you need, that sounds pretty great.
capabilities(7)
. – 0xC0000022L Jun 01 '18 at 20:21