The infamous /run migration

When I saw that a new release of OpenRC was made that finally took the step of migrating our setup to the “new standard” /run directory I was honestly thrilled: for once, the setup I used on my router is no longer a special case but it looks a lot more like the rule: /var/run directories need to be recreated, as the default /run is in a tmpfs filesystem.

The fact that this version of OpenRC has been removed without a replacement it did bother me a bit, especially in the regards of LXC because I had to make changes to the cgroups handling — since this version of OpenRC also uses cgroups when using the new init script style (it doesn’t do it if you call start-stop-daemon yourself though), I had to stop mounting /cgroups myself, otherwise it wouldn’t be able to start any guest container, as OpenRC mounts its own copy of said filesystem, trying (and, as far as I can tell, failing) to behave more like systemd.

At any rate I did the migration on most of my systems for the sake of testing it before doing so in production. As far as I can tell none of my init scripts misbehaved, which is positive. On the other hand, there seem to be some trouble with what concerns other scripts, in particular munin cron scripts … d’oh!

For the sake of using the lowest possible privilege to do any given job, the munin cron script, the one that generates the actual HTML content that is served by Apache is running as a mostly unprivileged user — on the other hand, the node daemon is usually running as root and dropping to nobody’s privileges when executing most of the plugins; some require super user privileges, on either standard systems (for instance smartd based plugins) or at least on hardened (the original if_ plugin, that accessed /proc; the current version, both upstream and in Gentoo, was modified by me to use /sys which is available to non-privileged users as well, even on hardened).

At any rate this seems to show that there still isn’t something properly set up with the way OpenRC prepares /run: the privileges to /run/lock should probably be root:uucp 0775 and that is not the case right now, not on all systems at least.. and Munin should use that directory to store the lock file.

Oh well, time to find a better workaround locally, I guess.

Running git-daemon under an unprivileged user

Some more notes about the setup I’m following for the vserver (where this blog and xine’s bugtracker’s run, the last one I think was similar, but about awstats. You can see the running thread: running stuff as user rather than root, especially if the user has no access to any particular resource.

So this time my target is git-daemon; I already set it up some time ago to run as nobody (just changed the start-stop-daemon parameters) but there is some problem with that: you either give access to the git repositories to world, or to nobody, which might be used by other services too. Also, there has been a lot of development in git-daemon in the past months, to the point that now it really looks like a proper daemon, included privilege dropping, which makes it very nice with respect to security issues.

So here we go with setting up git-daemon to run as unprivileged user; please note first of all that I’ll also apply along these lines the fix to bug 238351 (git-daemon reported crashed by OpenRC), since I’m doing the same thing locally and it looks quite nicer to do it at once rather than multiple times.

I’m also going to assume a slightly different setup than the one I’m using myself, as it’s the one I’d like to convert soon enough: multi-user setup, with multiple system users (not gitosis-based) being able to publish their GIT repositories. This means that together with a git-daemon user, we’re going to have a git-users group for the users who are able to publish (and thus write to) git repositories:

# useradd -m -d /var/lib/git -s /sbin/nologin git-daemon
# groupadd git-users
# chmod 770 /var/lib/git
# setfacl -d -m u:git-daemon:rx /var/lib/git
# setfacl -m g:git-users:rwx /var/lib/git
# setfacl -d -m:git-users:- /var/lib/git

This way, the users in the git-users group may create subdirectories (and files) in /var/lib/git, but only git-daemon (-and other git-users-) would be able to access them in reading (-the users can then further restrict the access by removing git-users access to their subdirectories, either directly or through a script-; edit: I modified the commands so that other git-users don’t have, by default, access to other users’ subdirectories, they can extend it further). Since most likely you want to provide gitweb (or equivalent) access to the repositories, you might want also to allow your webserver to access that; in my case, gitweb run as the lighttpd user (I haven’t got around to split the various CGIs yet), so I add this:

# setfacl -m u:lighttpd:rx /var/lib/git
# setfacl -d -m u:lighttpd:rx /var/lib/git

This way lighttpd will have access to /var/lib/git and by default to all the subdirectories created.

Now it’s time to set up the init script correctly, since the one that dev-util/git ships at the moment will execute git-daemon only as root. We’re going to change both the start and stop functions, and generically the init script too. The first step is to add a PIDFILE variable outside the functions, we’re going to call it /var/run/git-daemon.pid. The proper fix for the bug linked above allows an override for PIDFILE, but this is not important, to me at least, and should stay only in the official script. Of course /va/rrun is not accessible to the git-daemon user, but this is not the problem; since git-daemon can drop privileges by itself, it will create the pid file beforehand. In my original idea, I was thinking of using start-stop-daemon directly to change the git-daemon user so that it wouldn’t run at root at all, but since the wrapper is mostly a hack, to run as a different user, I decided (for now) to let git-daemon handle its privileges dropping. (It would be nice if some security people assessed what’s the best way to handle this to make it official policy to follow); in that case, a subdirectory to /var/run was needed, since it had to be accessed by an unprivileged user.

After adding the PIDFILE variable, you’ll have to change the invocation of start-stop-daemon; you have to remove the --background option to ssd and replace it with the --detach option to git-daemon itself, and add to the latter also the --pid-file, --user and --group options; you also need to add the --pidfile (look here: no dash!) option to both invocations of ssd (not to the git-daemon parameters!). At that point, just restart git-daemon and you’re done. The final script looks like this:

#!/sbin/runscript
# Copyright 1999-2008 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/dev-util/git/files/git-daemon.initd,v 1.3 2008/09/16 17:52:15 robbat2 Exp $

PIDFILE=/var/run/git-daemon.pid

depend() {
        need net
        use logger
}

start() {
        ebegin "Starting git-daemon"
                start-stop-daemon --start 
                --pidfile ${PIDFILE} 
                --exec /usr/bin/git -- daemon ${GITDAEMON_OPTS} 
                --detach --pid-file=${PIDFILE} 
                --user=git-daemon --group=nogroup
        eend $?
}

stop() {
        ebegin "Stopping git-daemon"
                start-stop-daemon --stop --quiet --name git-daemon 
                --pidfile ${PIDFILE}
        eend $?
}

I also dropped the --quiet option to ssd since I had to look for some error at startup some time ago (I also have –syslog option configured through the conf.d file).

Although most of these changes could be handled by conf.d alone, I think it’d be nice if the default script shipped with dev-util/git included not only the fix for the bug but also the privilege dropping: running git-daemon as root is, in my opinion, craziness.