Bug 34163

Summary: ping: socket: Operation not permitted под пользователем в контейнере
Product: Sisyphus Reporter: Vitaly Lipatov <lav>
Component: iputilsAssignee: Mikhail Efremov <sem>
Status: CLOSED FIXED QA Contact: qa-sisyphus
Severity: normal    
Priority: P3 CC: ender, ldv, sem
Version: unstable   
Hardware: all   
OS: Linux   
URL: https://bugs.openvz.org/browse/OVZ-6744
Bug Depends on: 27995    
Bug Blocks:    

Description Vitaly Lipatov 2017-11-09 15:13:25 MSK
control ping [public|restricted|netadmin]
исправно меняет права на каталог
/usr/libexec/ping/
что позволяет ограничить запуск команды ping выбранной категории пользователей.

В то же самое время на файле ping стоит SIGD, файл принадлежит группе iputils,
а в /lib/sysctl.d/70-iputils.conf указано, какая группа может пинговать:
# Allow ping socket creation for group iputils
net.ipv4.ping_group_range = 101 101
101 это iputils
(см. https://bugzilla.altlinux.org/show_bug.cgi?id=27995#c8)

Впрочем, нахождение в этой группе не помогает:
[lav@builder64 ~]$ id | tr ',' '\n' | grep iputils
101(iputils)

[lav@builder64 ~]$ ping ya.ru
ping: socket: Операция не позволена

capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, NULL) = -1 EFAULT (Bad address)
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=0, permitted=0, inheritable=0}) = 0
socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP) = -1 EACCES (Permission denied)
socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) = -1 EPERM (Operation not permitted)
socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6) = -1 EPROTONOSUPPORT (Protocol not supported)
socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) = -1 EPERM (Operation not permitted)

на всякий случай добавлю, что история происходит в контейнере OpenVZ.
Comment 1 Mikhail Efremov 2017-11-09 16:17:30 MSK
А что говорит sysctl net.ipv4.ping_group_range?
Comment 2 Vitaly Lipatov 2017-11-09 16:47:21 MSK
(В ответ на комментарий №1)
> А что говорит sysctl net.ipv4.ping_group_range?
$ sudo sysctl net.ipv4.ping_group_range
net.ipv4.ping_group_range = 101	101
Comment 3 Mikhail Efremov 2017-11-09 19:40:16 MSK
Хм, а покажите strace от root'а. То, что от пользователя под strace ping не работает - это понятно, там SGID.
Comment 4 Vitaly Lipatov 2017-11-09 23:27:15 MSK
(В ответ на комментарий №3)
> Хм, а покажите strace от root'а. То, что от пользователя под strace ping не
> работает - это понятно, там SGID.
Вывод $ sudo strace ping ya.ru

capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, NULL) = -1 EFAULT (Bad address)
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=1<<CAP_CHOWN|1<<CAP_DAC_OVERRIDE|1<<CAP_DAC_READ_SEARCH|1<<CAP_FOWNER|1<<CAP_FSETID|1<<CAP_KILL|1<<CAP_SETGID|1<<CAP_SETUID|1<<CAP_SETPCAP|1<<CAP_LINUX_IMMUTABLE|1<<CAP_NET_BIND_SERVICE|1<<CAP_NET_BROADCAST|1<<CAP_NET_ADMIN|1<<CAP_NET_RAW|1<<CAP_IPC_LOCK|1<<CAP_IPC_OWNER|1<<CAP_SYS_CHROOT|1<<CAP_SYS_PTRACE|1<<CAP_SYS_ADMIN|1<<CAP_SYS_BOOT|1<<CAP_SYS_NICE|1<<CAP_SYS_RESOURCE|1<<CAP_SYS_TTY_CONFIG|1<<CAP_MKNOD|1<<CAP_LEASE|1<<CAP_AUDIT_WRITE|1<<CAP_SETFCAP, permitted=1<<CAP_CHOWN|1<<CAP_DAC_OVERRIDE|1<<CAP_DAC_READ_SEARCH|1<<CAP_FOWNER|1<<CAP_FSETID|1<<CAP_KILL|1<<CAP_SETGID|1<<CAP_SETUID|1<<CAP_SETPCAP|1<<CAP_LINUX_IMMUTABLE|1<<CAP_NET_BIND_SERVICE|1<<CAP_NET_BROADCAST|1<<CAP_NET_ADMIN|1<<CAP_NET_RAW|1<<CAP_IPC_LOCK|1<<CAP_IPC_OWNER|1<<CAP_SYS_CHROOT|1<<CAP_SYS_PTRACE|1<<CAP_SYS_ADMIN|1<<CAP_SYS_BOOT|1<<CAP_SYS_NICE|1<<CAP_SYS_RESOURCE|1<<CAP_SYS_TTY_CONFIG|1<<CAP_MKNOD|1<<CAP_LEASE|1<<CAP_AUDIT_WRITE|1<<CAP_SETFCAP, inheritable=1<<CAP_CHOWN|1<<CAP_DAC_OVERRIDE|1<<CAP_DAC_READ_SEARCH|1<<CAP_FOWNER|1<<CAP_FSETID|1<<CAP_KILL|1<<CAP_SETGID|1<<CAP_SETUID|1<<CAP_SETPCAP|1<<CAP_LINUX_IMMUTABLE|1<<CAP_NET_BIND_SERVICE|1<<CAP_NET_BROADCAST|1<<CAP_NET_ADMIN|1<<CAP_NET_RAW|1<<CAP_IPC_LOCK|1<<CAP_IPC_OWNER|1<<CAP_SYS_CHROOT|1<<CAP_SYS_PTRACE|1<<CAP_SYS_ADMIN|1<<CAP_SYS_BOOT|1<<CAP_SYS_NICE|1<<CAP_SYS_RESOURCE|1<<CAP_SYS_TTY_CONFIG|1<<CAP_MKNOD|1<<CAP_LEASE|1<<CAP_AUDIT_WRITE|1<<CAP_SETFCAP}) = 0
capset({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=1<<CAP_SETGID|1<<CAP_SETUID, permitted=1<<CAP_SETGID|1<<CAP_SETUID|1<<CAP_NET_ADMIN|1<<CAP_NET_RAW, inheritable=0}) = 0
prctl(PR_SET_KEEPCAPS, 1)               = 0
setreuid(100, 100)                      = 0
prctl(PR_SET_KEEPCAPS, 0)               = 0
capset({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=0, permitted=1<<CAP_NET_ADMIN|1<<CAP_NET_RAW, inheritable=0}) = 0
...
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, NULL) = -1 EFAULT (Bad address)
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=0, permitted=1<<CAP_NET_ADMIN|1<<CAP_NET_RAW|1<<CAP_SYS_ADMIN, inheritable=0}) = 0
capset({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=1<<CAP_NET_RAW, permitted=1<<CAP_NET_ADMIN|1<<CAP_NET_RAW|1<<CAP_SYS_ADMIN, inheritable=0}) = 0
socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP) = -1 EACCES (Permission denied)
socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) = 5
socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6) = -1 EPROTONOSUPPORT (Protocol not supported)
socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) = 7
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, NULL) = -1 EFAULT (Bad address)
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=1<<CAP_NET_RAW, permitted=1<<CAP_NET_ADMIN|1<<CAP_NET_RAW|1<<CAP_SYS_ADMIN, inheritable=0}) = 0
capset({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=0, permitted=1<<CAP_NET_ADMIN|1<<CAP_NET_RAW|1<<CAP_SYS_ADMIN, inheritable=0}) = 0

...
socket(AF_INET, SOCK_DGRAM, IPPROTO_IP) = 8
connect(8, {sa_family=AF_INET, sin_port=htons(1025), sin_addr=inet_addr("87.250.250.242")}, 16) = 0
getsockname(8, {sa_family=AF_INET, sin_port=htons(55995), sin_addr=inet_addr("192.168.0.62")}, [16]) = 0
close(8)                                = 0
setsockopt(5, SOL_RAW, ICMP_FILTER, ~(1<<ICMP_ECHOREPLY|1<<ICMP_DEST_UNREACH|1<<ICMP_SOURCE_QUENCH|1<<ICMP_REDIRECT|1<<ICMP_TIME_EXCEEDED|1<<ICMP_PARAMETERPROB), 4) = 0
setsockopt(5, SOL_IP, IP_RECVERR, [1], 4) = 0
setsockopt(5, SOL_SOCKET, SO_SNDBUF, [324], 4) = 0
setsockopt(5, SOL_SOCKET, SO_RCVBUF, [65536], 4) = 0
getsockopt(5, SOL_SOCKET, SO_RCVBUF, [131072], [4]) = 0
fstat(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(136, 9), ...}) = 0
write(1, "PING YA.ru (87.250.250.242) 56(8"..., 50PING YA.ru (87.250.250.242) 56(84) bytes of data.
) = 50
setsockopt(5, SOL_SOCKET, SO_TIMESTAMP, [1], 4) = 0
setsockopt(5, SOL_SOCKET, SO_SNDTIMEO, "\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0
setsockopt(5, SOL_SOCKET, SO_RCVTIMEO, "\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16) = 0
getpid()                                = 5108
rt_sigaction(SIGINT, {sa_handler=0x7f71f72262c0, sa_mask=[], sa_flags=SA_RESTORER|SA_INTERRUPT, sa_restorer=0x7f71f61a3be0}, NULL, 8) = 0
rt_sigaction(SIGALRM, {sa_handler=0x7f71f72262c0, sa_mask=[], sa_flags=SA_RESTORER|SA_INTERRUPT, sa_restorer=0x7f71f61a3be0}, NULL, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=0x7f71f72262b0, sa_mask=[], sa_flags=SA_RESTORER|SA_INTERRUPT, sa_restorer=0x7f71f61a3be0}, NULL, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
ioctl(1, TCGETS, {B38400 opost isig icanon echo ...}) = 0
ioctl(1, TIOCGWINSZ, {ws_row=59, ws_col=211, ws_xpixel=0, ws_ypixel=0}) = 0
capget({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, NULL) = -1 EFAULT (Bad address)
capset({version=_LINUX_CAPABILITY_VERSION_3, pid=0}, {effective=0, permitted=0, inheritable=0}) = 0
sendto(5, "\10\0A\220\23\364\0\1V\234\4Z\0\0\0\0\204\261\4\0\0\0\0\0\20\21\22\23\24\25\26\27"..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("87.250.250.242")}, 16) = 64
Comment 5 Dmitry V. Levin 2017-11-10 00:08:11 MSK
(In reply to comment #0)
> на всякий случай добавлю, что история происходит в контейнере OpenVZ.

А в хост-системе работает.
Comment 6 Vitaly Lipatov 2017-11-10 01:10:51 MSK
(В ответ на комментарий №5)
> (In reply to comment #0)
> > на всякий случай добавлю, что история происходит в контейнере OpenVZ.
> 
> А в хост-системе работает.

У меня нет хост-систем на Сизифе. Напрягся и поставил iputils из Сизифа:
# apt-get install http://ftp.altlinux.org/pub/distributions/ALTLinux/Sisyphus/files/x86_64/RPMS/iputils-20161105-alt2.x86_64.rpm

[lav@windsor ~]$ ls -l /usr/libexec/ping/ping
-rwx--s--x 1 root iputils 64472 сен 21 20:26 /usr/libexec/ping/ping
[lav@windsor ~]$ id lav | grep --color iputils
[lav@windsor ~]$ 

Работает, как ожидается.
Comment 7 Dmitry V. Levin 2017-11-10 02:06:05 MSK
(In reply to comment #6)
> (В ответ на комментарий №5)
> > (In reply to comment #0)
> > > на всякий случай добавлю, что история происходит в контейнере OpenVZ.
> > 
> > А в хост-системе работает.
> 
> У меня нет хост-систем на Сизифе. Напрягся и поставил iputils из Сизифа:
> # apt-get install
> http://ftp.altlinux.org/pub/distributions/ALTLinux/Sisyphus/files/x86_64/RPMS/iputils-20161105-alt2.x86_64.rpm
> 
> [lav@windsor ~]$ ls -l /usr/libexec/ping/ping
> -rwx--s--x 1 root iputils 64472 сен 21 20:26 /usr/libexec/ping/ping
> [lav@windsor ~]$ id lav | grep --color iputils
> [lav@windsor ~]$ 
> 
> Работает, как ожидается.

Я думаю, что настройка доступа ping_group_range к ping sockets, которые создются с помощью socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP), не может нормально работать в linux-контейнерах любой природы, поскольку gid, соответствующий группе iputils в хост-системе, в принципе не должен совпадать с gid, отображённым с помощью gid_map из аналогичного gid в linux-контейнере.

Локально вы можете обойти это ограничение, указав в ping_group_range широкий диапазон.

Дистрибутивно это ограничение можно обойти, добавив ping'у в control новые возможные состояния public-in-container и netadmin-in-container, похожие на традиционные public и netadmin в прежних iputils, которые не поддерживали ping sockets.
Comment 8 Vitaly Lipatov 2017-11-10 03:07:46 MSK
(В ответ на комментарий №7)
...
> Я думаю, что настройка доступа ping_group_range к ping sockets, которые
> создются с помощью socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP), не может
> нормально работать в linux-контейнерах любой природы, поскольку gid,
> соответствующий группе iputils в хост-системе, в принципе не должен совпадать с
> gid, отображённым с помощью gid_map из аналогичного gid в linux-контейнере.
Но может быть надо собрать просто новую версию, в которой будет коммит
https://github.com/iputils/iputils/commit/d141cb6e4ee3388f0508afa0f6368aaa1236778c#diff-3bbcff584f2ee1c8172d9e280209ebe4
Comment 9 Vitaly Lipatov 2017-11-12 20:09:01 MSK
(В ответ на комментарий №7)
...
> Локально вы можете обойти это ограничение, указав в ping_group_range широкий
> диапазон.
[lav@builder64]$ sudo sysctl net.ipv4.ping_group_range="1 99999999999999"
[lav@builder64]$ sudo sysctl net.ipv4.ping_group_range
net.ipv4.ping_group_range = 1	276447231
[lav@builder64]$ ping ya.ru
ping: socket: Операция не позволена
Comment 10 Repository Robot 2018-05-21 19:08:47 MSK
iputils-20161105-alt3 -> sisyphus:

Fri Jan 26 2018 Mikhail Efremov <sem@altlinux> 20161105-alt3
- Add {public,netadmin}_caps facilities (closes: #34163).
- Patches from upstream:
  + Use libidn2 instead of libidn.
  + Fix ping to local IPv6 interfaces.