It\'s very annoying to have this limitation on my development box, when there won\'t ever be any users other than me.
I\'m aware of the standard workarounds, but non
I know this is an old question, but now with recent (>= 4.3) kernels there is finally a good answer to this - ambient capabilities.
The quick answer is to grab a copy of the latest (as-yet-unreleased) version of libcap from git and compile it. Copy the resulting progs/capsh
binary somewhere (/usr/local/bin
is a good choice). Then, as root, start your program with
/usr/local/bin/capsh --keep=1 --user='your-service-user-name' \
--inh='cap_net_bind_service' --addamb='cap_net_bind_service' \
-- -c 'your-program'
In order, we are
cap_net_bind_service
capability to the inherited & ambient setsbash -c 'your-command'
(since capsh
automatically starts bash with the arguments after --
)There's a lot going on under the hood here.
Firstly, we are running as root, so by default, we get a full set of capabilities. Included in this is the ability to switch uid & gid with the setuid
and setgid
syscalls. However, ordinarily when a program does this, it loses its set of capabilities - this is so that the old way of dropping root with setuid
still works. The --keep=1
flag tells capsh
to issue the prctl(PR_SET_KEEPCAPS)
syscall, which disables the dropping of capabilities when changing user. The actual changing of users by capsh
happens with the --user
flag, which runs setuid
and setgid
.
The next problem we need to solve is how to set capabilities in a way that carries on after we exec
our children. The capabilities system has always had an 'inherited' set of capabilities, which is " a set of capabilities preserved across an execve(2)" [capabilities(7)]. Whilst this sounds like it solves our problem (just set the cap_net_bind_service
capability to inherited, right?), this actually only applies for privileged processes - and our process is not privileged anymore, because we already changed user (with the --user
flag).
The new ambient capability set works around this problem - it is "a set of capabilities that are preserved across an execve(2) of a program that is not privileged." By putting cap_net_bind_service
in the ambient set, when capsh
exec's our server program, our program will inherit this capability and be able to bind listeners to low ports.
If you're interested to learn more, the capabilities manual page explains this in great detail. Running capsh
through strace
is also very informative!