CLOVER🍀

That was when it all began.

Linux CapabilitiesとDocker

Dockerを使う時に「--cap-add」とか「--privileged」とか使うことがありますが、あまりわかってないなぁと思って
少し見てみることに。

Docker run reference / Runtime privilege and Linux capabilities

Capabiliiesというのは、Linuxでの特権ユーザーに割り当てられている権限をグルーピングしたものだとか。

capabilities(7) - Linux manual page

Man page of CAPABILITIES

これを、グルーピング単位にオン/オフができます、と。

Dockerでは、コンテナに対してこの権限グループを「--cap-add」で追加したり、反対に「--cap-drop」で削除したりできる
ということですね。

Dockerコンテナにデフォルトで許可されているCapabilitiesはドキュメントに記載がありますが、ソースコードとしては
以下に定義されているようです。
※現時点でのmasterブランチで見てみたら、ファイルパスが変わっていましたが

https://github.com/moby/moby/blob/v19.03.12/oci/defaults.go

capabilityを設定しているのは、このあたり。

https://github.com/moby/moby/blob/v19.03.12/daemon/oci_linux.go#L138-L153

またもうひとつ、「--privileged」というオプションがあり、こちらは「Give extended privileges to this container」という
説明になっています。「拡張特権」、ですね。

ドキュメントをもう少し見てみましょう。

When the operator executes docker run --privileged, Docker will enable access to all devices on the host as well as set some configuration in AppArmor or SELinux to allow the container nearly all the same access to the host as processes running outside containers on the host.

「--privileged」オプションを付与すると、Dockerはホスト上のすべてのデバイスへのアクセスを有効にし、コンテナがホスト上の
コンテナ外部で実行されているプロセスと同じようにホストにアクセスできるようにする、と書いてあります。

ソースコードだと、このあたりでしょうか。

https://github.com/moby/moby/blob/v19.03.12/daemon/exec_linux.go#L25-L33

LinuxCapabilitiesというのは、こちら。

https://github.com/opencontainers/runtime-spec/blob/v1.0.1/specs-go/config.go#L59-L72

先程のmanページ(Linux Capabilities)を見ると、これは「Thread capability sets」を表すようです。

capabilities(7) - Linux manual page

Man page of CAPABILITIES

スレッドはcapability setを持ち、各capability setには、「-cap-add」で指定しているような個々のcapabilityを指定することが
できます

が、ソースコードを見てみると「GetAllCapabilities」ですべてのcapabilityを指定しているように見えますね。すべての
capability setに、全部の特権を与えているということでしょう。

その定義はこちら。

https://github.com/moby/moby/blob/v19.03.12/oci/caps/utils.go#L61-L68

https://github.com/moby/moby/blob/v19.03.12/oci/caps/utils.go#L13-L30

https://github.com/syndtr/gocapability/blob/d98352740cb2c55f81556b63d4a1ec64c5a319c2/capability/enum.go

スレッドも含めてまるっと特権を与えたかったら、「--privileged」ということですね。

基準にした環境は、こちら。

$ docker version
Client: Docker Engine - Community
 Version:           19.03.12
 API version:       1.40
 Go version:        go1.13.10
 Git commit:        48a66213fe
 Built:             Mon Jun 22 15:45:44 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.12
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.10
  Git commit:       48a66213fe
  Built:            Mon Jun 22 15:44:15 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683