Open eli-schwartz opened 1 year ago
... the solution is not to start all daemons as root, the solution is to perform killing of that pid after dropping privileges to the command_user.
I don't think anyone ever said that the solution is to start all daemons as root. There are essentially two types of daemons:
The mistake is launching the first type as a non-root user and then letting it create a PID file in an unprivileged location. OpenRC doesn't necessarily even know what user such a daemon will run as. For example, the user account is often specified in the daemon's configuration file, e.g.
# grep User /etc/clamd.conf
User clamav
and arbitrary configuration formats aren't parseable in POSIX shell. That design isn't spectacular but it makes sense when you consider the context -- it had to work with a very dumb service manager like sysvinit that doesn't maintain any state between start/stop. And it still works pretty well so long as you don't mistake it for the second type.
There's no problem with the second type because OpenRC handles the PID file (securely) for you. And almost all daemons are of the second type (or provide a compatible option) today because it's what works best with systemd.
To summarize, the PID handling is secure so long as the service script writer chooses the best way to launch the daemon. There are insane corner cases with goofball software obviously but in general you probably just want to launch everything in the foreground and let OpenRC background it these days.
As a side note, it sounds unbelievable, but AFAIK there is no POSIX way to drop privileges. Unrelated to PID files, there's a race condition in checkpath
that would benefit greatly from one.
there is no POSIX way to drop privileges
in the shell
of course the C daemons know how to do it
services started by start-stop-daemon get stopped by it, in c code, so we can (and very likely should) drop privileges before sending stop signals
even if "properly" set up services won't have a problem, there's no real reason to leave the door open to mistakes. services that start as root and drop privs themselves will still have root kill them, but now services that don't will have a sane safety guard, makes the process less foot-gunny
tl;dr
Killing a service via pidfile should use the command_user privileges.
Background
I was looking around in the documentation on writing openrc services due to a discussion about a znc service dying where someone mentioned "i bet its bc openrc wants to run it as root". I figured this is wrong, because surely openrc allows marking a service as needing to be started as non-root.
It turns out that openrc does support this: https://github.com/OpenRC/openrc/blob/master/service-script-guide.md#dont-write-your-own-startstop-functions You're supposed to set
command_user="user:group"
.However, it is later on dis-recommended and warned against as being a security vulnerability to start services as non-root: https://github.com/OpenRC/openrc/blob/master/service-script-guide.md#pid-files-should-be-writable-only-by-root
Why is this a problem?
What does this even mean? It's bad to start services as an unprivileged user that cannot do arbitrary things to root, because the service manager grants absolute trust to the pidfile and allow it to DoS any process it likes, so instead we grant absolute trust to the daemon itself and believe in its pinky promise to drop privileges later?
This documentation appears to have been written by the author of http://michael.orlitzky.com/cves/cve-2017-18284.xhtml which I was linked to as supporting rationale for this documentation warning.
IMO this is totally wrong and indicative of an underlying flaw in openrc itself. If daemons are insecure because they write a pidfile as non-root, owned by non-root, that root then kills...
... the solution is not to start all daemons as root, the solution is to perform killing of that pid after dropping privileges to the command_user.
/cc @thesamesam @orlitzky