Closed sfan5 closed 2 years ago
It has euid 0 (root), but not the required capability (CAP_NET_RAW) -- socket() returning EPERM -- so it can't use ICMP. Give it CAP_NET_RAW and it will work for IPv4. You might need CAP_NET_ADMIN for IPv6 if you're doing link-local pings, though, since that requires one to bind to a specific interface to work.
Why this regressed, I don't know. Maybe an strace of the working version (with the same base operating system image, please) ?
localhost:~/fping-5.0# ./src/fping --version
./src/fping: Version 5.0
localhost:~/fping-5.0# strace ./src/fping 8.8.8.8
execve("./src/fping", ["./src/fping", "8.8.8.8"], 0xffffef313ff8 /* 18 vars */) = 0
set_tid_address(0xffffbb817230) = 254
brk(NULL) = 0xaaaad053c000
brk(0xaaaad053e000) = 0xaaaad053e000
mmap(0xaaaad053c000, 4096, PROT_NONE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xaaaad053c000
mprotect(0xaaaaaedc9000, 4096, PROT_READ) = 0
socket(AF_INET, SOCK_RAW, IPPROTO_ICMP) = -1 EPERM (Operation not permitted)
socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP) = 3
fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK|O_LARGEFILE) = 0
socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6) = -1 EPERM (Operation not permitted)
socket(AF_INET6, SOCK_DGRAM, IPPROTO_ICMPV6) = 4
fcntl(4, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK|O_LARGEFILE) = 0
getuid() = 0
getpid() = 254
setsockopt(3, SOL_SOCKET, SO_TIMESTAMPNS_OLD, [1], 4) = 0
setsockopt(4, SOL_SOCKET, SO_TIMESTAMPNS_OLD, [1], 4) = 0
bind(3, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(47842), sin_addr=inet_addr("0.0.0.0")}, [16]) = 0
bind(4, {sa_family=AF_INET6, sin6_port=htons(0), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::", &sin6_addr), sin6_scope_id=0}, 28) = 0
getsockname(4, {sa_family=AF_INET6, sin6_port=htons(47843), sin6_flowinfo=htonl(0), inet_pton(AF_INET6, "::", &sin6_addr), sin6_scope_id=0}, [28]) = 0
rt_sigprocmask(SIG_UNBLOCK, [RT_1 RT_2], NULL, 8) = 0
rt_sigaction(SIGQUIT, {sa_handler=0xaaaaaedb2dc0, sa_mask=[INT QUIT], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0xffffbb7b7de8}, NULL, 8) = 0
rt_sigaction(SIGINT, {sa_handler=0xaaaaaedb2dc0, sa_mask=[INT QUIT], sa_flags=SA_RESTORER|SA_RESTART, sa_restorer=0xffffbb7b7de8}, NULL, 8) = 0
mmap(NULL, 1048580, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xffffbb66a000
sendto(3, "\10\0=\35\272\342\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 64, 0, {sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("8.8.8.8")}, 16) = 64
pselect6(5, [3 4], NULL, NULL, {tv_sec=0, tv_nsec=500001000}, {sigmask=NULL, sigsetsize=8}) = 1 (in [3], left {tv_sec=0, tv_nsec=482108226})
recvmsg(3, {msg_name={sa_family=AF_INET, sin_port=htons(0), sin_addr=inet_addr("8.8.8.8")}, msg_namelen=128 => 16, msg_iov=[{iov_base="\0\0E\35\272\342\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., iov_len=128}], msg_iovlen=1, msg_controllen=0, msg_flags=MSG_CTRUNC}, MSG_TRUNC) = 64
writev(1, [{iov_base="8.8.8.8 is alive", iov_len=16}, {iov_base="\n", iov_len=1}], 28.8.8.8 is alive
) = 17
pselect6(5, [3 4], NULL, NULL, {tv_sec=0, tv_nsec=0}, {sigmask=NULL, sigsetsize=8}) = 0 (Timeout)
exit_group(0) = ?
+++ exited with 0 +++
Eh, it notices it can't do ICMP, switches to UDP mode, sends packets and receives the reply. But from the strace, it looks like it doesn't recognize the reply as the target being alive.
I feared the regression was related to the changes I submitted to drop privileges later (required for IPv6 link-local to work on Linux), but it doesn't look related to that change at all. Instead, it looks like some logic got broken in 5.1.
I will leave the debugging of the other changes to someone who knows the code better...
This seems caused by commit 31f76f607158997ab3967d0ee61404b263e754b3
This is inside an systemd-nspawn container running Alpine Linux edge (aarch64).
ping_group_range
is configured on the host. Did an update yesterday and it no longer works, I think the last working version was 5.0.strace output attached: You can see it receives responses but seems to ignore them.