Granting a capability to a service

Florian Weimer fweimer at
Mon Jul 20 14:27:35 UTC 2015

On 07/20/2015 04:21 PM, Steve Grubb wrote:
> On Saturday, July 18, 2015 10:42:43 AM Florian Weimer wrote:
>> Let's assume I want to start a service as an ordinary user, but allow to
>> bind it to a privileged port.  The program implementing the service does
>> not manipulate capabilities in any way.
>> I came up with with this system unit for testing purposes:
>> [Unit]
>> Description=Test unit
>> [Service]
>> Type=oneshot
>> ExecStart=/usr/sbin/getpcaps self
>> Capabilities=cap_net_bind_service+ep
>> SecureBits=keep-caps
>> User=fweimer
>> StandardOutput=journal
>> However, this does not work, the capability set remains empty.  Is there
>> a way to achieve what I want?
>> The algorithm documented in capabilities(7) suggests that retaining
>> effective capabilities across an execve system call absolutely requires
>> file capabilities (the inheritable part).
> No. You can start off as root, then change to your target uid retaining, then
> open the socket. Just do it right away.

Sorry, but I don't see the contradiction.

As far as I can tell, you have to do all this before the execve
(including the socket creation), or after the execve (and then execve
with UID=0).  Without resorting to fscaps, it is not possible to set up
the capabilities and user before the execve, and create the socket after
it.  Without fscaps with a UID which is not 0, the capabilities are lost
on execve.

>> The only way to bypass that
>> if you perform the execve call with UID 0 (i.e., the literal UID 0, not
>> a capability).
> Using libcap-ng, its 3 lines of code. Assuming the desired uid is 500:
>      capng_clear(CAPNG_SELECT_BOTH);
>      if (capng_change_id(500, 500, CAPNG_DROP_SUPP_GRP | CAPNG_CLEAR_BOUNDING))
>          error();

But this requires changing the implementation of the service, right?

Florian Weimer / Red Hat Product Security

More information about the devel mailing list