You are not logged in.

#1 2020-08-17 09:53:24

stefan
Member
Registered: 2013-03-22
Posts: 104

[solved] Are capabilities checked correctly? aka. ping w/o capability

Hi, brooding over Linux capabilities, I was trying to follow an
example about file capabilities, along the lines of [1].  The argument
is, that `ping` works for unprivileged users, without needing the SUID
bit set, because it comes the `cap_net_raw`.

What I do not understand: `ping` works just as well without any
capabilities.  Here's the setup:

Unprivileged user:

    $ id
    uid=1001(foo) gid=100(users) groups=100(users)

The shell has no capabilities:

    $ grep Cap /proc/$$/status
    CapInh: 0000000000000000
    CapPrm: 0000000000000000
    CapEff: 0000000000000000
    CapBnd: 000000ffffffffff
    CapAmb: 0000000000000000

The usuual `ping` works:

    $ ping -c1 192.168.0.161
    PING 192.168.0.161 (192.168.0.161) 56(84) bytes of data.
    64 bytes from 192.168.0.161: icmp_seq=1 ttl=64 time=3.31 ms

    --- 192.168.0.161 ping statistics ---
    1 packets transmitted, 1 received, 0% packet loss, time 0ms
    rtt min/avg/max/mdev = 3.309/3.309/3.309/0.000 ms

because its executable comes with privileges:

    $ ls -l "$(which ping)"
    -rwxr-xr-x 1 root root 69k Nov 13  2019 /usr/bin/ping  # printed red
    $ getcap "$(which ping)"
    /usr/bin/ping = cap_net_raw+ep

Make my own copy of `ping`, without privileges:

    $ cp "$(which ping)" /tmp/foo
    $ getcap /tmp/foo   # no output
    $ l /tmp/foo
    -rwx------ 1 foo users 69k Aug 17 11:28 /tmp/foo  # no SUID bit

So why does the following work?

    $ /tmp/foo -c1 192.168.0.161
    PING 192.168.0.161 (192.168.0.161) 56(84) bytes of data.
    64 bytes from 192.168.0.161: icmp_seq=1 ttl=64 time=2.88 ms

    --- 192.168.0.161 ping statistics ---
    1 packets transmitted, 1 received, 0% packet loss, time 0ms
    rtt min/avg/max/mdev = 2.876/2.876/2.876/0.000 ms

I would have expected a complaint.  (which is actually the case on a
SuSE SLES 12 system).

Can anyone reproduce?  Did I get something wrong?

Cheers
Stefan

[1]: https://blog.container-solutions.com/li … n-practice

Last edited by stefan (2020-08-18 20:07:29)

Offline

#2 2020-08-17 12:59:48

loqs
Member
Registered: 2014-03-06
Posts: 17,326

Re: [solved] Are capabilities checked correctly? aka. ping w/o capability

Offline

#3 2020-08-17 13:35:15

stefan
Member
Registered: 2013-03-22
Posts: 104

Re: [solved] Are capabilities checked correctly? aka. ping w/o capability

What does that mean?  What does it do?  By which mechanics does it work?

Offline

#4 2020-08-17 13:40:47

loqs
Member
Registered: 2014-03-06
Posts: 17,326

Re: [solved] Are capabilities checked correctly? aka. ping w/o capability

# ping(8) without CAP_NET_ADMIN and CAP_NET_RAW
# The upper limit is set to 2^31-1. Values greater than that get rejected by
# the kernel because of this definition in linux/include/net/ping.h:
#   #define GID_T_MAX (((gid_t)~0U) >> 1)
# That's not so bad because values between 2^31 and 2^32-1 are reserved on
# systemd-based systems anyway: https://systemd.io/UIDS-GIDS.html#summary
-net.ipv4.ping_group_range = 0 2147483647

net.ipv4.ping_group_range is documented in https://www.kernel.org/doc/Documentatio … sysctl.txt

Offline

#5 2020-08-17 14:05:51

stefan
Member
Registered: 2013-03-22
Posts: 104

Re: [solved] Are capabilities checked correctly? aka. ping w/o capability

Thanks.  I'll try to put this into more words, correct me if I got it wrong...

So there's this file with that line:

$ grep net.ipv4.ping_group_range /usr/lib/sysctl.d/*
/usr/lib/sysctl.d/50-default.conf:-net.ipv4.ping_group_range = 0 2147483647

According to sysctl.d(5), this configures kernel parameters at boot.  The parameter in question is `net.ipv4.ping_group_range`.  The leading dash seems to suppress error messages if the parameter would not exist in the kernel.

The two integers describe a range of GIDs, members of which may “create ping sockets”, i.e.

$ sysctl net.ipv4.ping_group_range
net.ipv4.ping_group_range = 0   2147483647

allows everyone who's a member of a group with 0 ≤ GID ≤ 2147483647 to ping.

A rationale for having this may be to make ping work inside rootless Podman containers, but I do not know if that's the only one, nor whether there's a reason to have this by default.

Offline

#6 2020-08-18 07:48:07

stefan
Member
Registered: 2013-03-22
Posts: 104

Re: [solved] Are capabilities checked correctly? aka. ping w/o capability

Nah, not yet.  I need to post a follow-up question:  Trying to reproduce the example from my previous postings, I've disabled `ping_group_range` as documented, to exclude all groups from the exemption:

# id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),19(log)

# sysctl net.ipv4.ping_group_range='1 0'
net.ipv4.ping_group_range = 1 0

# ping -c1 localhost
PING localhost(localhost (::1)) 56 data bytes
64 bytes from localhost (::1): icmp_seq=1 ttl=64 time=0.066 ms

--- localhost ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.066/0.066/0.066/0.000 ms

# getcap $(which ping)
/usr/bin/ping = cap_net_raw+ep

And as unprivileged user:

$ id
uid=1001(foo) gid=100(users) groups=100(users)

$ sysctl net.ipv4.ping_group_range
net.ipv4.ping_group_range = 1   0

$ ping -c1 localhost
PING localhost(localhost (::1)) 56 data bytes
64 bytes from localhost (::1): icmp_seq=1 ttl=64 time=0.055 ms

--- localhost ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.055/0.055/0.055/0.000 ms

$ getcap $(which ping)
/usr/bin/ping = cap_net_raw+ep

So`ping` still works, as expected due to having `cap_net_raw`.  So let's trythis with our own copy of ping:

$ cp $(which ping) /tmp/foo
$ chmod 700 /tmp/foo
$ getcap /tmp/foo  # no output

$ /tmp/foo -c1 localhost
/tmp/foo: socket: Operation not permitted

So far, so good.  But why does the following *not* work:

# setcap cap_net_raw+ep /tmp/foo   # NOTE: performed by root

$ getcap /tmp/foo
/tmp/foo = cap_net_raw+ep

$ /tmp/foo -c1 localhost
/tmp/foo: socket: Operation not permitted

Offline

#7 2020-08-18 15:26:20

loqs
Member
Registered: 2014-03-06
Posts: 17,326

Re: [solved] Are capabilities checked correctly? aka. ping w/o capability

/tmp is mounted nosuid by default.

man 8 mount wrote:

nosuid Do not honor set-user-ID and set-group-ID bits or file capabilities when executing programs from this filesystem.

Offline

#8 2020-08-18 20:07:13

stefan
Member
Registered: 2013-03-22
Posts: 104

Re: [solved] Are capabilities checked correctly? aka. ping w/o capability

Amazing.  Yes, when I repeat the experiment, but copy `ping` to `$HOME` instead of `/tmp`, I observe the desired effect.  I'm a little bit frustrated/scared by the multitude of variables that affect the permissions of a process (and I have not yet begun to dig into user namespace hierarchies)...

@loqs: Thank you very much!

Offline

Board footer

Powered by FluxBB