連載の第42回 で
ファイルケーパビリティは安全のためにコピーすると設定が外れます。
なんてことを書いてますが、同僚から「Arch Linux でやるとなぜか ping が実行できてしまう」という情報が。確かに Arch でやると実行できてしまいます。
$ lsb_release -d Description: Arch Linux $ cp /usr/bin/ping . $ getcap ./ping $ ./ping -c 1 127.0.0.1 PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data. 64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.025 ms --- 127.0.0.1 ping statistics --- 1 packets transmitted, 1 received, 0% packet loss, time 0ms rtt min/avg/max/mdev = 0.025/0.025/0.025/0.000 ms
strace とかで見てみるとどうも SOCK_RAW
でなく SOCK_DGRAM
を使ってる模様。どうやらこれらしい。hayajo さんからも同じ情報を頂いて自信を持って、これを手がかりにググってみると、
- ICMP sockets (lwn.net)
- ICMP sockets (lwn.net)
icmp(7) にも記載が。えー、2.6.39 から?
$ man icmp :(snip) ping_group_range (two integers; default: see below; since Linux 2.6.39) Range of the group IDs (minimum and maximum group IDs, inclu‐ sive) that are allowed to create ICMP Echo sockets. The default is "1 0", which means no group is allowed to create ICMP Echo sockets.
いやー、Linux 奥が深いですね。こんなの知りませんでした。Arch を確認してみると確かに設定されています。
$ sysctl -a 2>/dev/null | grep ping_group_range net.ipv4.ping_group_range = 0 2147483647
Plamo だと
$ /sbin/sysctl -a 2>/dev/null | grep ping net.ipv4.ping_group_range = 1 0
Arch の値はやりすぎ感あるのでとりあえず 0〜65534 とすると、
$ sudo sysctl -w net.ipv4.ping_group_range="0 65534" net.ipv4.ping_group_range = 0 65534 $ /sbin/sysctl -n net.ipv4.ping_group_range 0 65534
設定できたので、
$ cp /bin/ping . $ /sbin/getcap ./ping $ ./ping -c1 127.0.0.1 PING 127.0.0.1 (127.0.0.1) 56(84) バイトのデータ 64 バイト応答 送信元 127.0.0.1: icmp_seq=1 ttl=64 時間=0.013ミリ秒 --- 127.0.0.1 ping 統計 --- 送信パケット数 1, 受信パケット数 1, パケット損失 0%, 時間 0ミリ秒 rtt 最小/平均/最大/mdev = 0.013/0.013/0.013/0.000ミリ秒
実行できました。
ちなみに「安全のためにコピーしたら外れる」とか書きましたが、cp コマンドでも CAP_SETFCAP
ケーパビリティがあれば --preserve=xattr
とかやればファイルケーパビリティ保存したままコピーされますね。
(補足・2019-11-29) Twitter で systemd がそのように設定していると教えていただきました。ありがとうございます。
arch linux だとというか、 systemd が v243 でその設定するようになったはず。 https://t.co/QmnkVwvGuN
— NAKAMURA Yoshitaka (@nakamuray) 2019年11月27日
https://t.co/srbSkIaU6m
— NAKAMURA Yoshitaka (@nakamuray) 2019年11月27日
ここに書かれてるのがその件についてではないかと。
* This release enables unprivileged programs (i.e. requiring neither setuid nor file capabilities) to send ICMP Echo (i.e. ping) requests by turning on the "net.ipv4.ping_group_range" sysctl of the Linux kernel for the whole UNIX group range, i.e. all processes. This change should be reasonably safe, as the kernel support for it was specifically implemented to allow safe access to ICMP Echo for processes lacking any privileges. If this is not desirable, it can be disabled again by setting the parameter to "1 0".