TenForward

技術ブログ。はてなダイアリーから移転しました

ping コマンドの file capability(2)

(理解が不十分なので間違っている所があれば優しく教えてください)

さて、ping コマンドの file capability(1) - TenForward で紹介したように ping コマンドの File capability は Permitted のみが有効になっていて、Effective ビットはオン(+e)になっていません。これで ping が実行できる理由は説明したとおりですが、+e が設定されていない理由は「不要だから」というだけの理由ではありません。

「なんで +e ないんだろう?」とつぶやいていると WhiteAnthrax さんが調べて教えてくれました!ありがとうございます!

これは

www.projectatomic.io

に書かれている通りです。Docker コマンド内の ping コマンドの実行で問題が起こるからということです。

まず Docker コンテナでは、普通に docker run すると cap_net_admin が許可されません。cap_net_adminping -m のように実行する際に必要です(man ping すると -m は "use mark to tag the packets going out." とのことです)。一方で ping を普通に実行する際に必要な cap_net_raw は許可されています。つまり Docker コンテナ内では ping コマンドで -m をつけても目的は達成できません。

ここで(これは明確に man capabilities には書いてない気がするけど…)

  • File capability で +e すると、指定したすべての capability が取得できない場合、コマンドを実行した瞬間に実行は失敗する

ということのようです。

特権が必要なシステムコールの実行が行われる、行われないに関わらず、すべての capability の取得に失敗すると、コマンド自体が実行できないということです。ping --help のような特権が不要な実行であってもです。

ということは、

  • Docker コンテナ内で cap_net_admin,cap_net_raw+ep と設定してしまうと、cap_net_admin が取得できないので、cap_net_raw のみが必要な実行であっても ping コマンドを実行した瞬間にコマンド実行が失敗する

ということです。

今回の ping コマンドはプログラム中で自身で capability をチェックして Permitted がオンであれば capset() を使って Effective を有効にしていますので、+p とだけしておくと、たとえ cap_net_admin が取得できなくてもコマンド実行は成功します。

つまりプログラム中で権限のチェックを行って capability をセットしていますので、

となります。それ以外のシステムコールは問題なく実行されるわけです。

ping -m と実行すると、プログラム中で cap_net_admin のチェックをしているところのみ失敗します。つまり "mark" だけが失敗して、cap_net_raw が必要な処理は行われます。

https://bugzilla.redhat.com/show_bug.cgi?id=1142311#c24 によると

[root@29b49db23971 /]# /opt/ping/ping -m 123 -c1 10.3.1.1
PING 10.3.1.1 (10.3.1.1) 56(84) bytes of data.
Warning: Failed to set mark 123
64 bytes from 10.3.1.1: icmp_seq=1 ttl=62 time=0.327 ms

のように mark 処理の部分だけ失敗して、それ以外の処理は行われるようです(試してませんw)。

というわけで +e してしまうと、ping コマンドはヘルプすら表示できず、本来の実行できる処理も実行できなくなるので、+p のみが設定されているということです。

(2019-09-30 追記) 『これは明確に man capabilities には書いてない気がするけど…』と書きましたが、id:udzura さんから man 2 execve

EPERM  A "capability-dumb" applications would not obtain the full set
       of permitted capabilities granted by the executable file.  See
       capabilities(7).

という説明があると教えてもらいました!(これでも曖昧ではあるけど "the full set" とあるのできっと…)