ping: icmp open socket: Operation not permitted

今日「某所のサーバがおかしいから見てほしい」とお願いされて、そのサーバにSSHでログインし、pingを実行しようとしたら、なんとpingがうてない

$ ping 172.xx.xx.xxx
ping: icmp open socket: Operation not permitted


ほほう。困った。・・・が、rootユーザで実行すると、pingを飛ばす事はできる。
ケーパビリティ*1で権限まわりを細かく切っている雰囲気もない、、、と思っていたら、

$ ls -l /bin/ping
-rwxr-xr-x 1 root root 37312  9月 27  2009 /bin/ping

ん?よく見たらSUIDがセットされていない。

# chmod u+s /bin/ping
# ls -l /bin/ping
-rwsr-xr-x 1 root root 37312  9月 27  2009 /bin/ping

というわけで、SUIDのフラグを立てる。

$ ping 172.xx.xx.xx
PING 172.xx.xx.xx (172.xx.xx.xx) 56(84) bytes of data.
64 bytes from 172.xx.xx.xx: icmp_seq=1 ttl=64 time=0.207 ms
64 bytes from 172.xx.xx.xx: icmp_seq=2 ttl=64 time=0.251 ms
64 bytes from 172.xx.xx.xx: icmp_seq=3 ttl=64 time=0.248 ms

--- 172.xx.xx.xx ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.207/0.235/0.251/0.023 ms

無事、pingは飛びましたとさ。というお話でした。
(なぜSUIDが付いていなかったのか、については、後で依頼された当人にヒアリングすると、以前に/bin直下をごにょごにょした時にやらかしてしまったとのことでした。)

メモ(参考)

$ strace ping -c 1 172.xx.xx.xx
execve("/bin/ping", ["ping", "-c", "1", "172.xx.xx.xx"], [/* 21 vars */]) = 0
brk(0)                                  = 0x2b32817ef000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b3267e2d000
uname({sys="Linux", node="hostname", ...}) = 0
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or directory)
open("/etc/ld.so.cache", O_RDONLY)      = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=51323, ...}) = 0
mmap(NULL, 51323, PROT_READ, MAP_PRIVATE, 3, 0) = 0x2b3267e2e000
close(3)                                = 0
open("/lib64/libresolv.so.2", O_RDONLY) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\2402 \3117\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=92736, ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b3267e3b000
mmap(NULL, 2181864, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x2b326802e000
mprotect(0x2b326803f000, 2097152, PROT_NONE) = 0
mmap(0x2b326823f000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x11000) = 0x2b326823f000
mmap(0x2b3268241000, 6888, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2b3268241000
close(3)                                = 0
open("/lib64/libc.so.6", O_RDONLY)      = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\220\332!\3017\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=1717800, ...}) = 0
mmap(NULL, 3498328, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x2b3268243000
mprotect(0x2b3268390000, 2097152, PROT_NONE) = 0
mmap(0x2b3268590000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x14d000) = 0x2b3268590000
mmap(0x2b3268595000, 16728, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x2b3268595000
close(3)                                = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b326859a000
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b326859b000
arch_prctl(ARCH_SET_FS, 0x2b326859aaf0) = 0
mprotect(0x2b3268590000, 16384, PROT_READ) = 0
mprotect(0x2b326823f000, 4096, PROT_READ) = 0
mprotect(0x2b326802c000, 4096, PROT_READ) = 0
munmap(0x2b3267e2e000, 51323)           = 0
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = -1 EPERM (Operation not permitted)
getuid()                                = 12345
setuid(12345)                           = 0
socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(1025), sin_addr=inet_addr("172.xx.xx.xx")}, 16) = 0
getsockname(3, {sa_family=AF_INET, sin_port=htons(46388), sin_addr=inet_addr("172.xx.xx.yy")}, [16]) = 0
close(3)                                = 0
dup(2)                                  = 3
fcntl(3, F_GETFL)                       = 0x8002 (flags O_RDWR|O_LARGEFILE)
brk(0)                                  = 0x2b32817ef000
brk(0x2b3281810000)                     = 0x2b3281810000
fstat(3, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 1), ...}) = 0
mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x2b3267e2e000
lseek(3, 0, SEEK_CUR)                   = -1 ESPIPE (Illegal seek)
write(3, "ping: icmp open socket: Operatio"..., 48ping: icmp open socket: Operation not permitted
) = 48
close(3)                                = 0
munmap(0x2b3267e2e000, 4096)            = 0
exit_group(2)                           = ?

$