ping: socket: Operation not permitted Ubuntu docker image
Hi i am new to docker and linux. I am trying to ping a particular ip address from a python file in a container built on ubuntu 18.04 base.
I get the following error when the kubernetes pod container is ran on CentOS OS but it runs fine on Ubuntu OS
sudo: effective uid is not 0, is /usr/bin/sudo on a file system with the 'nosuid' option set or an NFS file system without root privileges?
I am trying to run the container as a normal user. I have a security context in the container deployment yaml as below:
fsGroup: 2000
runAsNonRoot: true
runAsUser: 1000In the docker file i am trying to create a normal user and add it to sudoers grp as below
RUN adduser --disabled-password --gecos '' <normal user>
RUN adduser <normal user> sudo
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
USER <normal user>python file which calls the ping command as follows
subprocess.check_call(f"sudo ping -c 3 {address}") 1 Answer
Rationale
The error message you face with Kubernetes on CentOS already gives a hint about how sudo is working: It makes use of the setuid bit to have it effectively executed as owner of the executable, intended to be root, regardless which user executes it. Two conditions need to be met for this to work:
- The underlying filesystem needs to be mounted without the
nosuidoption, which prevents setuid functionality. You can list all mounts with with this flag e.g. via:mount | grep nosuid - The owner of the file needs to be
root, which you can check via:
The owner's mode should showls -l "$(which sudo)"rws, where thesis the setuid bit, which needs to be present as well, of course.
Needless to say that both conditions need to be met on host system level when using a host system kernel feature. I'm no expert with the different container platforms, whether and how they mount the container images and do UNIX user namespace sandboxing, so that sudo within the container may naturally be ineffective for granting host system capabilities.
Solutions
Granting a user full passwordless sudo permissions only to run ping in my personal opinion is no good idea anyway for security reasons, in case it is even possible within Docker. There are safer options to achieve this, I'll start with the one which should definitely work for your use case and is IMHO the safest from security point of view and continue with two other general solutions, while not recommending them.
- It is possible to define UNIX groups which shall have ICMP listen permissions without requiring root privileges. Some Linux distributions even do this by default, the common init system systemd as well does this via their upstream default configuration:
This allows all possible UNIX users ICMP permissions, the group range can be narrowed down to a single UNIX group only, of course. It needs to be applied on the container's host system.echo 'net.ipv4.ping_group_range = 0 2147483647' > /etc/sysctl.d/99-ping.conf sysctl -p /etc/sysctl.d/99-ping.conf - Raw network socket capabilities can be granted via the
pingexecutable directly to all users which execute it:
This is how manysetcap 'cap_net_raw+ep' "$(which ping)"pingimplementations/packages ship by default, but it theoretically grants much more permissions than ICMP listening only. - The
pingexecutable itself can have the setuid bit so that it is effectively executed asrootuser in every case:
Somechmod +s "$(which ping)"pingimplementations/packages ship like this by default, but needless to say that this is the worst options from security point of view.
In your case, solutions 2 and 3 would need to be applied within the container to the container's ping executable and do only work when there is no sandboxing for executable capabilities respectively UNIX users, i.e. the root user within the container is the same root user on the host for solution 3. That sudo does not work indicates that the the last condition may not be met. Already these limitations in combination with containers and the security benefits IMHO clearly underlines the benefit of solution 1.