2

I need to run a container as non-root user by default. However a specific process inside this container needs to execute a binary that needs cap_net_admin capabilities (e.g: ip command).

I tried running the container with '--privileged' flag, assigning file capability cap_net_admin to 'ip' binary, as well as changing the group to the user's group. This did not work. What is the correct way to get this working?

# cat Dockerfile
FROM  ubuntu:21.04
RUN apt-get update
RUN apt-get install -f -y iproute2
RUN chgrp nogroup /bin/ip
RUN chmod g+x /bin/ip
RUN setcap 'cap_net_admin+epi' /bin/ip
USER nobody


# docker build .
Successfully built be565bc8f52d

# docker run --rm --user nobody  --privileged -it be565bc8f52d /bin/bash
nobody@9834cfaa833f:/$ getcap /bin/ip
/bin/ip cap_net_admin=eip
nobody@9834cfaa833f:/$ ls -lhrt /bin/ip
-rwxr-xr-x 1 root nogroup 626K Mar 17  2021 /bin/ip
nobody@9834cfaa833f:/$ groups nobody
nobody : nogroup
nobody@9834cfaa833f:/$  cat proc/self/status | grep Cap
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
nobody@9834cfaa833f:/$ ip link add dummy0 type dummy
RTNETLINK answers: Operation not permitted

Note: With older docker version, this was working with setcap and privileged flag. Probably it stopped working due to the fix for this CVE.

# docker --version
Docker version 20.10.14, build a224086
m.divya.mohan
  • 2,261
  • 4
  • 24
  • 34
  • Giving setuid permission got it working . i.e adding "RUN chmod u+s /bin/ip" in Dockerfile. Is this the right way, or any other options? – m.divya.mohan Apr 26 '22 at 14:08
  • Perhaps this binary needs more than a single capability? Try `setcap =ep /bin/ip` and see if that works. If so, you can explore dropping different capabilities until you find the ones it actually needs. – Tinkerer Apr 26 '22 at 14:53
  • @Tinkerer `setcap =ep` does not help. ```nobody@99c5eff1ef68:/$ getcap /bin/ip /bin/ip =ep nobody@99c5eff1ef68:/$ ip link add dummy0 type dummy bash: /usr/sbin/ip: Operation not permitted nobody@99c5eff1ef68:/$``` – m.divya.mohan Apr 26 '22 at 16:53
  • Can you say a little more about the end goal of the container? Normally Docker fully manages the container network environment, and commands like `ip` can't do anything useful. – David Maze Apr 26 '22 at 23:55
  • I think you are running into some sketchy code in `ip` itself. It looks like it is _Capability hostile_ in some way. The `ip` source code seems to [attempt to drop capabilities except in some specific circumstances](https://git.kernel.org/pub/scm/network/iproute2/iproute2.git/tree/ip/ip.c#n183). – Tinkerer Apr 27 '22 at 02:11
  • @DavidMaze This container implements OpenCompute SAI spec. "Adapter host" as mentioned here https://github.com/opencomputeproject/SAI/blob/master/doc/spec.md – m.divya.mohan Apr 27 '22 at 04:53

1 Answers1

3

Elaborating on my comment to the question, I think this is a problem with the ip code's attempt to suppress Ambient capabilities except in one specific command line case.

I've suggested a fix in this bug report: https://github.com/shemminger/iproute2/issues/62 (which appears to have been deleted, since this was not how iproute2 wants to receive bug reports). I was directed to try again with this email thread, so we can see how that report turns out.

I did develop a partial workaround you might want to try:

    $ sudo setcap cap_net_admin=ie ./ip
    $ sudo capsh --inh=cap_net_admin --user=`whoami` --
    $ ./ip ...

This works by using inheritable file capabilities instead of the permitted ones you were relying on. The ip code seems to prefer inheritable capabilities over permitted ones.

Tinkerer
  • 865
  • 7
  • 9