最近社内でLinux capabilitiesの話題がでていて「そういえばちゃんと理解していないな」と思ったので、夜ちょこちょこと技術エントリとかmanとかを読んでいました。
- Linux Capability - ケーパビリティについての整理 - ローファイ日記
- 第42回 Linuxカーネルのケーパビリティ[1]:LXCで学ぶコンテナ入門 -軽量仮想化環境を実現する技術|gihyo.jp … 技術評論社
- 明日使えない Linux の capabilities の話 - @nojima's blog
- [linux] /sbin/capsh - hibomaの日記
- ケイパビリティ - mrtc0.log
結構な頻度で同僚のエントリがヒットするのが良いです。エントリを見つけたら「わからなければ社内でカジュアルに聞ける」という福利厚生付き。
manをPro契約しているDeepLで翻訳して一気に読んでやろうと思ったら Capability
Permitted
Effective
などが日本語に訳されてしまってむしろ混乱してしまうという出来事もありしました。辞書設定すればいけるのかな。
プロセスやファイルのCapabilitiesを確認する方法
プロセス(スレッド)のケーパビリティを確認する方法は getpcaps
コマンドを、
ファイルのケーパビリティを確認する方法は getcap
コマンドを利用するのが良いでしょう。
Ubuntuならlibcap2-bin パッケージに入っているので、
$ sudo apt install libcap2-bin
で手に入れることができます。
使い方も
$ getpcaps [PID]
$ getcap [PATH]
とわかりやすいです。
capv
getpcaps
や getpcap
を使うのが一番良いのですが、ケーパビリティセットの表記が +ep
となっていたり、ファイルに(あまり意味はないが)Effectiveのケーパビリティだけをつけると
root@cd406362eb55:/go# touch /tmp/setcap_test root@cd406362eb55:/go# setcap all+e /tmp/setcap_test root@cd406362eb55:/go# getcap /tmp/setcap_test /tmp/setcap_test = root@cd406362eb55:/go#
となっていたり*1と、cap_from_text(3)形式になっていて、私はまだ慣れません。
まだわからなかったことがあるので、理解もかねてプロセスやファイルのケーパビリティを確認できるツールを作っています。
使い方は
$ capv -p [PID]
$ capv -f [PATH]
といった感じであまり変わらないのですが、表示だけ自分が理解をしやすいように変更しています。
root@cd406362eb55:/go# capv -p 1 P(permitted) [CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_FSETID CAP_KILL CAP_SETGID CAP_SETUID CAP_SETPCAP CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SYS_CHROOT CAP_MKNOD CAP_AUDIT_WRITE CAP_SETFCAP] P(inheritable) [CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_FSETID CAP_KILL CAP_SETGID CAP_SETUID CAP_SETPCAP CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SYS_CHROOT CAP_MKNOD CAP_AUDIT_WRITE CAP_SETFCAP] P(effective) [CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_FSETID CAP_KILL CAP_SETGID CAP_SETUID CAP_SETPCAP CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SYS_CHROOT CAP_MKNOD CAP_AUDIT_WRITE CAP_SETFCAP] P(bounding) [CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_FSETID CAP_KILL CAP_SETGID CAP_SETUID CAP_SETPCAP CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SYS_CHROOT CAP_MKNOD CAP_AUDIT_WRITE CAP_SETFCAP] P(ambient) []
先ほどのEffectiveのケーパビリティだけたてたファイルも
root@cd406362eb55:/go# capv -f /tmp/setcap_test F(permitted) [] F(inheritable) [] F(effective) 1
とEffectiveがついていることがわかるようになっています(ファイルケーパビリティのEffectiveだけ0か1)。
あと、これも私が理解のために実装している機能なのですが、 -p
と -f
の両方を指定すると、そのプロセスでファイルを実行(execve(2))したあとのスレッドのケーパビリティセットを表示できるようにしています。
root@cd406362eb55:/go# capv -p 1 -f /tmp/setcap_test P'(permitted) = (P(inheritable) & F(inheritable)) | (F(permitted) & P(bounding)) | P'(ambient) [] P'(inheritable) = P(inheritable) [CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_FSETID CAP_KILL CAP_SETGID CAP_SETUID CAP_SETPCAP CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SYS_CHROOT CAP_MKNOD CAP_AUDIT_WRITE CAP_SETFCAP] P'(effective) = F(effective) ? P'(permitted) : P'(ambient) [] P'(bounding) = P(bounding) [CAP_CHOWN CAP_DAC_OVERRIDE CAP_FOWNER CAP_FSETID CAP_KILL CAP_SETGID CAP_SETUID CAP_SETPCAP CAP_NET_BIND_SERVICE CAP_NET_RAW CAP_SYS_CHROOT CAP_MKNOD CAP_AUDIT_WRITE CAP_SETFCAP] P'(ambient) = (file is privileged) ? 0 : P(ambient) []
ただ、私が理解のために実装しているだけなので正しいかどうかは全く保証できません*2。
残り、securebitsとバウンディングセットについて、まだわかっていないので引き続き理解を進めようと思います。